具有整数增量的布尔表达式会产生意外结果

时间:2016-11-22 17:15:45

标签: c increment boolean-expression side-effects

    #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?

3 个答案:

答案 0 :(得分:3)

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

(请记住“乘法在加法之前”,或者在布尔逻辑AND之前出现在OR之前。由于运算符优先级,表达式变为完全括号(++x) || ((++y) && (++z));换句话说,||右边的所有内容{1}}是OR被忽略的右侧。)

左操作数++x增量x到2. z的评估被赋予||结果的布尔值,即1,因为它是全部沿。

<小时/> 顺便说一句,gcc警告说,我认为该陈述也是未定义的行为。 C 11标准草案n1570在6.5 / 2中说:

  

如果对标量物体的副作用相对于[...]没有排序   使用相同标量的值计算值   对象,行为未定义。

标准为此提供了i = ++i + 1;的示例。在你的右手边,z表达了这个角色。副作用是增量,值计算是&&子表达式。

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

答案 1 :(得分:2)

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

Short circuit evaluation

答案 2 :(得分:1)

逻辑运算||是所谓的&#34;短路&#34;或者&#34;懒惰&#34;操作。 如果此类运算符的左操作数正在评估逻辑true或非零,则不会评估右操作数。

所以在你的情况下:

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

++x正在评估2,使x等于2。这不是零,因此不评估右侧的所有内容,因此yz不会递增。并且z逻辑 OR操作的结果分配,即1。这就是你所看到的。