C中的运算符优先级?

时间:2017-12-15 10:15:10

标签: c operator-precedence

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;

3 个答案:

答案 0 :(得分:4)

您的表达式分组为

(++x >= (y * 2)) || ((y % 2) && (z++ % 2))

并将其分配给sum。这由C的语法指定。

另请注意,如果左侧是||,则1的右侧评估:这意味着z不会增加在那种情况下。

  1. 为避免疑义,++xx值,而z++价值z

  2. 另请注意,因为||排序点,即使您在右侧编写x++,也可以很好地定义表达式,而不是z++

  3. 调用此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)之前是否评估ab * 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中的21 * 2属于一起,但它没有告诉你应该用哪个顺序解决这个等式。您可以先计算1 + 1,或1 * 22 + 2来解决问题。

在表达式sum = ++x >= y * 2 || y % 2 && z++ % 2中,只有||&&指定了评估顺序。特别是这两个操作员有时被非正式地称为短路"评价。

对于其他运营商而言,评估顺序是未指定,这意味着我们无法了解或依赖它。编译器甚至不需要从表达式到表达式保持一致 - 原因是允许编译器在解析表达式树时生成最快的代码。

我们唯一可以知道的是,子表达式++xy * 2[result of ++x] >= [result of y * 2] 将在之前进行评估||的右侧。

反过来,如果||的右侧确实得到了评​​估,那么y % 2将在其余的子表达式之前得到评估,因为&&确实保证了评估的顺序它的操作数。