bool x = false, y = false, z = true;
if(x || y || z){}
or
if(x | y | z){}
第二个if语句是否对所有布尔值执行了一些“或”操作?把它们视为有字节吗? ex)(0000 | 0000 | 0001)= true ...
或者它是否像Java一样在布尔值上,它会评估表达式中的每一个bool,即使第一个是真的吗?
我想知道位运算符如何处理bool值。它等同于整数按位运算吗?
答案 0 :(得分:8)
效率取决于,逻辑或运算符||
是短路运算符
意味着如果您的示例中的x
为真,则不会评估y
或z
。
如果它是合乎逻辑的&&
,那么如果x
为false,则不会测试y
或z
。
重要的是要注意,此操作不作为指令存在
这意味着你必须使用测试和跳转指令。这意味着分支,这会减慢事情的速度。由于现代CPU是流水线的。
但真正的答案是,这与其他许多问题有关,因为短路操作的好处有时会超过成本。
在下面非常简单的示例中,您可以看到按位或|
是优越的。
#include <iostream>
bool test1(bool a, bool b, bool c)
{
return a | b | c;
}
bool test2(bool a, bool b, bool c)
{
return a || b || c;
}
int main()
{
bool a = true;
bool b = false;
bool c = true;
test1(a,b,c);
test2(a,b,c);
return 0;
}
以下是gcc-4.8使用-O3
生成的英特尔风格的汇编列表:
test1
汇编:
_Z5test1bbb:
.LFB1264:
.cfi_startproc
mov eax, edx
or eax, esi
or eax, edi
ret
.cfi_endproc
test2
议会:
_Z5test2bbb:
.LFB1265:
.cfi_startproc
test dil, dil
jne .L6
test sil, sil
mov eax, edx
jne .L6
rep; ret
.p2align 4,,10
.p2align 3
.L6:
mov eax, 1
ret
.cfi_endproc
你可以看到它有分支指令,这会弄乱管道。
但有时短路是值得的,例如
return x && deep_recursion_function();
<强>声明:强>
我总是在bools
上使用逻辑运算符。除非性能真的很重要,或者像test1
和test2
那样简单,但有很多bool。
在任何一种情况下,首先要确认你确实得到了改进。
答案 1 :(得分:3)
第二个是java |整数,有点或。由于C最初没有布尔类型,if语句将任何非零值读为true,因此您可以将其用作,但使用短路运算符通常更有效||相反,尤其是在调用返回条件的函数时。
我还想指出,短路可让您检查不安全的情况,例如if(myptr == NULL || myptr->struct_member < 0) return -1;
,同时使用按位,或者当myptr 为null时会出现段错误。