3
bool x = false, y = false, z = true;

if(x || y || z){}

or

if(x | y | z){}

第二个 if 语句是否对所有布尔值执行有点明智的“或”操作?把它们当作有字节来对待?例如)(0000 | 0000 | 0001)= 真...

还是它的行为像 Java | 在布尔值上,即使第一个为真,它也会评估表达式中的每个布尔值?

我想知道按位运算符如何处理布尔值。它是否等同于整数按位运算?

4

2 回答 2

8

效率取决于,逻辑 or 运算符||是短路运算符,这意味着如果x在您的示例中为真,它将不会评估yor z。如果它是一个逻辑&&然后如果x是假的,它不会测试yor z。重要的是要注意,此操作不作为指令存在,因此您必须使用测试和跳转指令。这意味着分支,这会减慢速度。由于现代 CPU 是流水线的。

但真正的答案是视情况而定,就像许多其他这种性质的问题一样,有时短路操作的好处超过了成本。

在以下极其简单的示例中,您可以看到按位 or|更好。

#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 生成的 intel 样式的程序集列表,其中-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. 除非性能真的很关键,或者可能是简单的情况,比如 in test1andtest2但有很多布尔值。在任何一种情况下,首先验证您确实得到了改进。

于 2013-09-05T21:35:06.190 回答
3

第二幕java | 在整数上,按位或。由于 C 最初没有布尔类型,if 语句读取任何非零为真,因此您可以使用它,但使用短路运算符 || 通常更有效 相反,尤其是在调用返回条件的函数时。

我还想指出,短路可以让您检查不安全的条件,例如if(myptr == NULL || myptr->struct_member < 0) return -1;,在使用按位或当 myptr空时会给您一个段错误。

于 2013-09-05T21:11:15.040 回答