评估C表达

时间:2010-10-12 15:16:40

标签: c++ c expression

int main() {
  int i = -3, j = 2,  k = 0, m;
  m = ++i || ++j && ++k;
  printf("%d %d %d %d\n", i, j, k, m);
  return 0;
}

我认为&&有更多的优先权||根据这个逻辑++j应该执行,但它永远不会执行,程序输出-2 2 0 1。这里发生了什么?有哪些中间步骤?

8 个答案:

答案 0 :(得分:14)

&&的优先级高于||,这意味着++i || ++j && ++k的解析为++i || (++j && ++k)

然而,这并没有改变||的RHS仅在LHS返回0时执行的事实。

优先顺序不会影响评估顺序。

答案 1 :(得分:7)

优先级对评估顺序没有影响(除非必要 - 由于优先权,某些子表达式可能需要在其他子表达式之前进行评估)。例如,在简单表达式中:

a() + b() + c() * d()

即使乘法优先于加法,编译器也可以按照自己喜欢的顺序自由执行对函数的调用,并且可以在执行乘法之前或之后调用a()b()。显然,它必须在执行乘法之前评估c()d()。如果这些函数具有副作用(如修改和使用全局变量),则不确定的评估顺序可能会导致意外结果。

但是,对于某些运营商而言,该标准确实规定了严格的评估顺序。这是关于||逻辑或运算符:

的说法
  

与按位|不同运算符,||运营商保证从左到右的评估;有   评估第一个操作数后的序列点。如果第一个操作数比较   不等于0,不评估第二个操作数。

因此||不仅提供了排序保证,而且还保证在某些条件下,第二个操作数根本不会被评估。

(它也对&&说了类似的内容 - 除了在这种情况下,如果第一个操作数的第一个计算结果为0,则不计算第二个操作数。但在您的示例中,||首先出现

提供一些排序保证的其他运算符包括逗号运算符和函数调用(它保证已经评估了参数,但不是评估这些参数的顺序)。

答案 2 :(得分:4)

C ++对逻辑运算符使用延迟评估 如果您写a || ba为真,则b将永远不会评估,因为即使b为假,结果也会为真。
同样,a && b如果b为假,则不会评估a

由于++i评估为真值,因此不会评估其他任何表达式。

答案 3 :(得分:1)

&安培;&安培;和||使用短路评估,即在表达式a中首先评估a& b a,如果是假,则整个表达式为假,b不进行评估。在|| b中,如果a为真,则不评估b。请注意,如果你超载&&或||短路规则将不再适用。 HTH

答案 4 :(得分:1)

C执行逻辑表达式的 short-circuiting ,因此对++i的评估足以证明m应该为真。

答案 5 :(得分:1)

  1. ||运算符强制从左到右评估,因此首先对表达式++i进行完全评估,结果为-2
  2. ||运算符会强制执行序列点,因此会应用副作用,i现在等于-2
  3. 表达式++i的结果不为0,因此根本不评估表达式++j && ++k
  4. 由于LHS非零,因此整个表达式++i || ++j && ++k的结果为1(true),其分配给m
  5. 只是为了回应其他人所说的,评价的优先顺序和顺序并不是一回事。

答案 6 :(得分:0)

您是否偶然想要输入:

m = ++i | ++j & ++k;

输出-2 3 1 -1

答案 7 :(得分:0)

  

m = ++ i || ++ j&& ++ K表;

由于&&的优先级高于||,因此表达式被解释为++i || (++j && ++k)

||正在短路,因此||运算符的右手操作数未被评估,因为++i返回非零值。