具有整数增量的布尔表达式给出了意想不到的结果

Boolean expression with integer increments gives unexpected results

    #include <stdio.h>
    int main()
    {
       int x, y, z; 
       x=y=z=1; 
       z = ++x || ++y && ++z; 
       printf("%d, %d, %d", x, y,z);
       return 0;
    }

我得到输出 2、1、1。我需要解释为什么 Y 在输出中是 1?

|| 运算符 短路; 如果左操作数不计算右操作数(并且从未执行副作用,即变量从不递增)计算结果为 != 0.

(请记住,"multiplication comes before addition" 或在布尔逻辑中 AND 出现在 OR 之前。由于运算符的优先级,表达式变成完全括起来的 (++x) || ((++y) && (++z));换句话说,右侧的所有内容|| 是 OR 忽略的右侧。)

左操作数 ++x 的计算将 x 递增到 2。z 被赋值为 || 结果的布尔值 1,因为它一直以来。


顺便说一句,gcc 发出警告,我认为该声明也是 未定义行为。 C 11 标准草案 n1570 在 6.5/2 中说:

If a side effect on a scalar object is unsequenced relative to [...] a value computation using the value of the same scalar object, the behavior is undefined.

标准为此给出了i = ++i + 1;的例子。在您的右侧表达式中,z 扮演着这个角色。副作用是增量,值计算是 && 子表达式。


1 有可能(即我不确定)它被定义为只要右侧从未被计算过。在这种情况下,编译器将被允许假定 ++x 永远不会为 0 并省略测试。为复杂的布尔表达式生成的代码将归结为 x 的增量。

|| ++y && ++z 部分未被评估,因为 ++x 已经为真。参见

Short circuit evaluation

逻辑运算||就是所谓的"short-circuit"或"lazy"运算。 如果此类运算符的左操作数评估为逻辑 true 或非零,则不会评估右操作数。

所以在你的情况下:

z = ++x || ++y && ++z; 

++x 正在计算 2,使 x 等于 2。这是非零的,所以右侧的所有内容都不会被评估,所以 yz 不会递增。而z是由逻辑OR操作的结果赋值的,即1。这就是你所看到的。