我想知道是否有人知道编译器解释以下代码的方式:
#include <iostream>
using namespace std;
int main() {
cout << (true && true || false && false) << endl; // true
}
这是真的,因为&amp;&amp;优先级高于||或因为||是一个短路运算符(换句话说,短路运算符是否忽略所有后续表达式,或只是下一个表达式)?
答案 0 :(得分:34)
&&
的优先级高于||
。
答案 1 :(得分:29)
答案 2 :(得分:22)
答案 3 :(得分:7)
&&
确实有higher precedence。
答案 4 :(得分:7)
两个事实解释了两个例子的行为。首先,&&
的优先级高于||
。其次,两个逻辑运算符都使用短路评估。
优先级往往与评估顺序混淆,但它是独立的。只要最终结果正确,表达式可以按任何顺序评估其各个元素。通常对于某些运算符来说,这意味着左边的值(LHS)可以在右边的值(RHS)之前或之后进行评估,只要在应用运算符本身之前对它们进行求值即可。
逻辑运算符具有特殊属性:在某些情况下,如果一方评估为特定值,则无论另一方的值如何,都知道运算符的值。为了使这个属性有用,C语言(以及每个类C语言的扩展)指定了逻辑运算符来评估RHS之前的LHS,并进一步仅评估RHS,如果其值 required 了解运营商的结果。
因此,假设TRUE
和FALSE
的通常定义,TRUE && TRUE || FALSE && FALSE
从左侧开始计算。第一个TRUE
不强制第一个&&
的结果,因此评估第二个TRUE
,然后评估表达式TRUE && TRUE
(为TRUE)。现在,||
知道它的LHS。更好的是,它的LHS迫使||
的结果被人知道,因此它会跳过对整个RHS的评估。
完全相同的评估顺序适用于第二种情况。由于||
的RHS无关紧要,因此不会对其进行评估,也不会调用infiniteLoop()
。
此行为是设计使然,非常有用。例如,您可以编写p && p->next
知道该表达式永远不会尝试取消引用NULL指针。
答案 5 :(得分:3)
“如果发生||运算符短路并使第二个&amp;&amp;表达式的执行短路,这意味着||运算符在第二个&amp;&amp;运算符之前被执行。这意味着左 - 到 - &amp;&amp;和||的正确执行(不是&amp;&amp;&amp;&quot; precedence)。“
不完全。
(xx && yy || zz && qq)
会像这样评估:
xx && yy
||
,并且该语句的第一部分为真,则跳过其余部分。||
之后检查下一位运营商,并对其进行评估:zz && qq
||
。根据我的理解,C ++的设计是为了在开始评估之前读取内容。毕竟,在我们的示例中,它不知道我们在&&
之后进行了第二次||
检查,直到它将其读入,这意味着它必须在||
之前读取它到达第二个&&
。因此,如果第一部分评估为true,它将不会在||
之后执行该部分,但如果第一部分评估为false,那么它将执行第一部分,读入{{1找到并评估第二部分,并使用第二部分的结果来确定最终结果。
答案 6 :(得分:1)
关于你的编辑:不会评估infiniteLoop()因为true || (无论如何)总是如此。使用true | (无论如何)如果应该执行什么。
答案 7 :(得分:1)
关于true && true || infiniteLoop() && infiniteLoop()
示例,由于两个特征的组合,两个无限循环调用都没有被评估:&amp;&amp;优先于||和||当左侧为真时短路。
如果&amp;&amp;和||具有相同的优先级,评估必须如下:
((( true && true ) || infiniteLoop ) && infiniteLoop )
(( true || infiniteLoop ) && infiniteLoop )
=> first call to infiniteLoop is short-circuited
(true && infiniteLoop) => second call to infiniteLoop would have to be evaluated
但由于&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;'s&amp;'s的优先权,评估实际上是
(( true && true ) || ( infiniteLoop && infiniteLoop ))
( true || ( infiniteLoop && infiniteLoop ))
=> the entire ( infiniteLoop && infiniteLoop ) expression is short circuited
( true )
答案 8 :(得分:1)
关于安德鲁的最新代码,
#include <iostream>
using namespace std;
bool infiniteLoop () {
while (true);
return false;
}
int main() {
cout << (true && true || infiniteLoop() && infiniteLoop()) << endl; // true
}
短路评估意味着保证不会执行对infiniteLoop
的调用。
然而,它以一种不正常的方式很有趣,因为C ++ 0x草案使无限循环 - 没有做任何未定义行为。这条新规则通常被认为是非常不受欢迎和愚蠢的,甚至是彻头彻尾的危险,但它有点潜入选秀。部分来自线程场景的考虑,一篇论文的作者认为它会简化某些事情的规则 - 或者其他相当不相关的事情。
因此,如果编译器位于C ++ 0x-conformance的“前沿”,那么即使它执行了对infiniteLoop
的调用,程序也可以终止某些结果。 !当然,使用这样的编译器,它也可能产生可怕的现象,鼻子守护进程......
令人高兴的是,如上所述,短路评估意味着保证不会执行呼叫。
干杯&amp;第h。,
答案 9 :(得分:1)
因为和/或/ true / false非常类似于* / + / 1/0(它们在数学上等同于ish),所以也是如此:
1 * 1 + 0 * 0 == 1
而且很容易记住...
所以是的,它与优先级和短路有关。如果将布局操作映射到相应的整数操作,则对布尔操作的优先级相当容易。
答案 10 :(得分:0)
这是一个顺序说明:
(true && true || false && false)
= ((true && true) || (false && false)) // because && is higher precedence than ||,
// like 1 + 2 * 3 = 7 (* higher than +)
= ((true) || (false))
= true
但请注意,如果是
(true || ( ... ))
然后右侧未被评估,因此没有调用任何函数,表达式将只返回true
。
答案 11 :(得分:-1)
简单的答案是&amp;&amp;优先级高于||。此外,代码不会被执行,因为它不需要知道布尔表达式的结果。是的,它是一个编译器优化。