在C ++中,在bool(s)之间执行&&
(逻辑)和&
(按位)之间有什么区别吗?
bool val1 = foo();
bool val2 = bar();
bool case1 = val1 & val2;
bool case2 = val1 && val2;
case1
和case2
是否完全相同,或者如果不相同,为什么会选择一个而不是另一个?是便宜的和bools便携式吗?
答案 0 :(得分:37)
standard保证false
转换为零,true
转换为1作为整数:
4.7整体转换
...
如果目的地类型是bool,请参阅4.12。如果源类型为bool,则将值false转换为零,将值true转换为一个。
因此,您提供的示例中的效果保证相同,并且100%便携。
对于您提供的情况,任何体面的编译器都可能生成相同的(最佳)代码。
但是,对于布尔表达式expr1
和expr2
,通常expr1 && expr2
与expr1 & expr2
相同,因为&&
执行“短” - 电路“评估。也就是说,如果expr1
评估为false
,则expr2
甚至不会被评估。这可能会影响性能(如果expr2
很复杂)和行为(如果expr2
有副作用)。 (但请注意,&
形式实际上可以更快,如果它避免了条件分支...出于性能原因而对这类事物进行操作几乎总是一个坏主意。)
因此,对于您给出的具体示例,您将值加载到局部变量中然后对它们进行操作,行为是相同的,并且很可能是性能。
在我看来,除非你特别依赖“短路”行为,否则你应该选择最明确表达你意图的表述。因此,对于逻辑AND使用&&
,对于bit-twiddling AND使用&
,并且任何有经验的C ++程序员都会发现您的代码很容易理解。
答案 1 :(得分:13)
使用逻辑和&&
时,如果左侧表达式为false,则不会评估右侧表达式。
许多C / C ++ / C#代码依赖于此,如:if (p != null && p->Foo())
。
对于您的示例,我将使用case2(逻辑和)。在处理位标志等时只使用按位。
但是,如果foo()和bar()只返回bool(0,1),那么case1和case2是相同的。
答案 2 :(得分:8)
虽然你不会在你的例子中看到它,但是有一点不同(好吧,两个)。
“&安培;”执行按位“AND”操作,意味着0x1 & 0x1 = 0x1
,但0x1 & 0x2 = 0x0
。 OTOH,“&&”是一个布尔/逻辑“AND”,意味着它将任何非零值视为TRUE,因此0x1 && 0x1 = TRUE
(通常表示为-1,即所有1 [或者它在C ++中表示为1,我忘了]),同时0x1 && 0x2 = TRUE
。
此外,“&&”是短路的,这意味着如果第一个操作数为FALSE,则不会评估第二个操作数。因此,FALSE & null_pointer->booleanField ==> null pointer exception
,FALSE && null_pointer->booleanField = FALSE
。
在某些情况下使用按位运算可能会有轻微的性能优势,但通常在评估布尔值时应使用double形式,以便您的代码独立于布尔值TRUE和FALSE的精确表示。
答案 3 :(得分:4)
在算法上没有区别,但使用&&允许您“检查”“短路”。也就是说,要判断case2,如果val1为false,那么编译后的代码没有理由检查val2的值以确定答案,其中case1需要实际的AND。
实际上,一个好的编译器会认识到这一点并生成相同的代码......这取决于你的编译器有多好。
答案 4 :(得分:2)
“&& ”是“条件逻辑”AND“ 它仅在第一个表达式为TRUE
时才计算第二个表达式“& ”是“非条件逻辑AND”< - (如果您正在使用布尔表达式) 它评估两个表达式
<强>此外强> “&安培;”是一个“按位”运算符,意味着它在位级操作。
这个例子可以让你更好地理解。
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)
答案 5 :(得分:0)
逻辑运营商&amp;&amp;和||在评估两个表达式以获得单个关系结果时使用。运营商&amp;&amp;对应于布尔逻辑运算AND。如果两个操作数都为真,则此操作结果为true,否则为false。
运营商||对应于布尔逻辑运算OR。如果两个操作数中的任何一个为真,则此操作结果为true,因此仅当两个操作数都为假时才为假。
答案 6 :(得分:-2)
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