int x=12;
int y=7;
int z=19;
int sum;
sum = ++x >= y * 2 || y % 2 && z++ % 2;
我对运营商优先级有点困惑?
编译器在上面的代码中读取的第一个条件是什么?
是否会首先评估y % 2 && z++ % 2
,因为&&
优先于||
,或者编译器仍然会从左到右,如果在最左边++x >= y * 2
则会短路是真的?即编译器将以下列方式读取代码?
sum = (++x >= y * 2 || y % 2 )&& z++ % 2;
答案 0 :(得分:4)
您的表达式分组为
(++x >= (y * 2)) || ((y % 2) && (z++ % 2))
并将其分配给sum
。这由C的语法指定。
另请注意,如果左侧是||
,则1
的右侧不评估:这意味着z
不会增加在那种情况下。
为避免疑义,++x
是x
的新值,而z++
是旧价值z
。
另请注意,因为||
是排序点,即使您在右侧编写x++
,也可以很好地定义表达式,而不是z++
。
调用此sum
的结果是混淆的练习。
答案 1 :(得分:4)
评估顺序与优先级(或相关性)无关。 &&
优先于||
的事实告诉您a || b && c
等同于a || (b && c)
。这不会告诉您是先评估a
还是b && c
。
在||
和&&
的情况下,标准指定首先计算左操作数(如果左操作数计算为true,则根本不评估右操作数(在{{的情况下) 1}})或false(分别为||
))。因此,在&&
中,我们知道订单为a || (b && c)
,a
,然后是b
(假设所有三个最终都被评估)。
对于大多数其他运营商而言,该标准未指定评估顺序,因此,例如,在c
中,我们知道它等同于a + b * c
,但我们不会&# 39;知道a + (b * c)
之前是否评估a
,b * c
之前是否评估b
。
答案 2 :(得分:1)
运算符优先级指定表达式如何解析,而不是如何计算。虽然相关,评估顺序是不同的!它由特定的运算符指定,或者未指定。
运算符优先级表示表达式等效于:
sum = ( ((++x) >= (y * 2)) || ((y % 2) && ((z++) % 2)) );
因为运算符具有以下优先顺序:
++ (postfix)
++ (prefix)
* % (same precedence)
>=
&&
||
如果您认为sum = ( ((++x) >= (y * 2)) || ((y % 2) && ((z++) % 2)) );
是一个难以理解的混乱,那么您是对的。然而,它与原始表达一样糟糕。如果你能避免,就不要在这样的一行上写多个操作符。
就我们的运营商优先权而言。它只是"胶水"特定的运算符和操作数。它没有规定评估的顺序。
将其视为数学:在数学表达式(1 + 1 + 1 * 2 + 2 + 2)
中,数学运算符的优先级保证1
中的2
和1 * 2
属于一起,但它没有告诉你应该用哪个顺序解决这个等式。您可以先计算1 + 1
,或1 * 2
或2 + 2
来解决问题。
在表达式sum = ++x >= y * 2 || y % 2 && z++ % 2
中,只有||
和&&
指定了评估顺序。特别是这两个操作员有时被非正式地称为短路"评价。
对于其他运营商而言,评估顺序是未指定,这意味着我们无法了解或依赖它。编译器甚至不需要从表达式到表达式保持一致 - 原因是允许编译器在解析表达式树时生成最快的代码。
我们唯一可以知道的是,子表达式++x
,y * 2
和[result of ++x] >= [result of y * 2]
将在之前进行评估||
的右侧。
反过来,如果||
的右侧确实得到了评估,那么y % 2
将在其余的子表达式之前得到评估,因为&&
确实保证了评估的顺序它的操作数。