验证参数为0或1

sha*_*cov 2 c

我有一个类型的参数num,int用户可以给它一个两个值:01.
我可以用明显的方法检查它:

if (num < 0 || num > 1)
    print("The parameter value is incorrect.\n");
Run Code Online (Sandbox Code Playgroud)

但我想知道是否有更好的(更快的?更少的代码?)这样做?

编辑
这是一些数据流代码,因此性能至关重要.我正在寻找一种更快的方式来运行此检查.

谢谢

Dav*_*aim 8

我会继续清晰而不是更少的角色:

if (num != 0 && num != 1){
    print("The parameter value is incorrect.\n");
}
Run Code Online (Sandbox Code Playgroud)

当它是凌晨2点并且你正在调试程序时,你想要的最后一件事是过度思考范围和按位操作.


Grz*_*ski 5

清除代码(天真)微优化

您实际上是在对实际编译器的行为做出错误的假设.在这两种情况下,这是:

if (num < 0 || num > 1) { ...
Run Code Online (Sandbox Code Playgroud)

if (num != 0 && num != 1) { ...
Run Code Online (Sandbox Code Playgroud)

一个优化编译器无论如何都会降低它变成最短的形式.您可能会看到,两者都生成相同的程序集,可能看起来像(x86平台):

cmp    $0x1,%eax
jbe    1e <foo+0x1e> # jump if below or equal
Run Code Online (Sandbox Code Playgroud)

这已经足够快了,因为cmp所有主要架构的指令都有一个周期的延迟.

最重要的是选择任何代码,使你的意图,未来的维护者清楚,让编译器完成它的工作.只需确保您使用适当的优化级别(例如-O2或更好)进行设置.


援助分支预测

但是,如果性能在这里非常重要(并且您将其描述为如此,不是吗?),那么您可以考虑另一种优化,即分支预测级别(假设您的CPU支持它).GCC具有__builtin_expect内在的,允许提示编译器,在大多数情况下,分支将被采用.

您可以使用__builtin_expect为编译器提供分支预测信息.一般来说,你应该更喜欢使用实际的配置文件反馈(-fprofile-arcs),因为程序员在预测程序实际执行情况方面是出了名的.但是,有些应用程序难以收集此数据.

举例来说,如果你有信心,该功能需要01在案件aproximately 99%的数量,那么你可以把它写成:

#define unlikely(x) __builtin_expect((x), 0)

if (unlikely(num != 0 && num != 1)) { ...
Run Code Online (Sandbox Code Playgroud)

  • @ shapiro.yaacov:它可能不会更快.`num&~1`可以编译为`test $ 0xfffffffe,%eax`,但仍然是`cmp`和`test`都是非常基本的指令,延迟只有一个周期.有关更多参考,请参阅[Agner的指令表](http://www.agner.org/optimize/instruction_tables.pdf). (2认同)