38

在 C++ 中,在 bool(s)之间做&&(逻辑) 和(按位)有什么区别吗?&

bool val1 = foo();
bool val2 = bar();

bool case1 = val1 & val2;
bool case2 = val1 && val2;

是否相同case1case2或者如果不是,它们究竟有何不同,为什么要选择一个而不是另一个?按位和布尔值可移植吗?

4

7 回答 7

42

标准保证false转换为零并true以整数形式转换为一:

4.7 积分转换

...

如果目标类型是 bool,请参见 4.12。如果源类型为 bool,则值 false 转换为零,值 true 转换为一。

所以你给出的例子中的效果保证是一样的,并且是100%可移植的。

对于您给出的情况,任何体面的编译器都可能生成相同的(最佳)代码。

但是,对于布尔表达式expr1expr2,一般情况下这expr1 && expr2与执行“短路”评估不同。也就是说,如果评估为,则甚至不会被评估。这会影响性能(如果很复杂)和行为(如果有副作用)。(但请注意,如果它避免条件分支,表单实际上可以更快......出于性能原因玩弄这类事情几乎总是一个坏主意。)expr1 & expr2&&expr1falseexpr2expr2expr2&

因此,对于您给出的特定示例,您将值加载到局部变量中然后对其进行操作,行为是相同的并且性能很可能是相同的。

在我看来,除非您特别依赖“短路”行为,否则您应该选择最清楚地表达您的意图的表述。因此,请使用&&逻辑 AND 和&位旋转 AND,任何有经验的 C++ 程序员都会发现您的代码易于理解。

于 2011-07-05T02:35:44.463 回答
17

使用逻辑 and&&时,如果左侧表达式为假,则不会计算右侧表达式。

很多 C/C++/C# 代码都依赖于此,例如:if (p != null && p->Foo()).

对于您的示例,我将使用 case2(逻辑与)。仅在处理位标志等时使用按位。

但是,如果 foo() 和 bar() 只返回 bool (0, 1) 那么 case1 和 case2 是一样的。

于 2011-07-05T02:39:44.933 回答
8

有一个区别(嗯,两个),虽然你不会在你的例子中看到它。

"&" 执行按位 "AND" 运算,意思是0x1 & 0x1 = 0x1, 但是0x1 & 0x2 = 0x0。OTOH,“&&”是一个布尔/逻辑“AND”,意味着它将任何非零值视为 TRUE,因此0x1 && 0x1 = TRUE(通常表示为 -1,即全为 [或者在 C++ 中可能表示为 1,我忘记了]),同时0x1 && 0x2 = TRUE也是。

此外,“&&”是短路的,这意味着如果第一个操作数为 FALSE,则不会计算第二个操作数。所以,当FALSE & null_pointer->booleanField ==> null pointer exception, FALSE && null_pointer->booleanField = FALSE.

在某些情况下使用按位运算可能会有轻微的性能优势,但通常在评估布尔值时应该使用双精度形式,以便您的代码独立于布尔值 TRUE 和 FALSE 的精确表示。

于 2011-07-05T02:44:38.637 回答
4

算法上没有区别,但是使用 && 可以让你“短路”检查。也就是说,要确定 case2,如果 val1 为假,那么编译的代码没有理由检查 val2 的值以确定答案,其中 case1 需要实际的 AND 发生。

实际上,一个好的编译器会识别这一点并生成相同的代码……这取决于你的编译器有多好。

于 2011-07-05T02:34:41.970 回答
4

&& ”是一个“条件逻辑“AND”,它仅在第一个表达式为 TRUE 时才计算第二个表达式

& ” 是一个“非条件逻辑与” <-- (如果你正在使用布尔表达式)它计算两个表达式


MOREOVER "&" 是一个“位”运算符,这意味着它在位级别上运行。

这个例子可以让你更好地理解。

4 = 00000100  // 'four' bit set
5 = 00000101  // 'four' bit and 'one' bit set

00000100 (4) & // AND: only keep bits set in both
00000101 (5)
--------
00000100 (4)

00000100 (4) | // OR: keep bits set in either
00000101 (5)
--------
00000101 (5)

00000100 (4) ^ //  EXCLUSIVE OR: keep bits only set in one but not the other
00000101 (5)
--------
00000001 (1)
于 2013-09-19T09:48:17.473 回答
0

逻辑运算符 && 和 || 在评估两个表达式以获得单个关系结果时使用。运算符 && 对应于布尔逻辑运算 AND。如果两个操作数都为真,则此运算结果为真,否则为假。

运算符 || 对应于布尔逻辑运算 OR。如果两个操作数中的任何一个为真,则此操作结果为真,因此只有当两个操作数本身都为假时才为假。

于 2012-12-02T12:11:18.970 回答
-1
int a = 0, b = 10;

if(a == 1 && (b/a) == 0) cout << "This is okay\n"; // the 2nd expression is never checked as the first one is false

cout << "Bingo\n";

if(a == 1 & (b/a) == 0) cout << "This is not okay\n"; // program crashes here trying to divide by zero

cout << "Bingo\n"; // this will never get printed
于 2015-07-26T15:06:57.663 回答