具有整数增量的布尔表达式给出了意想不到的结果
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"或"lazy"运算。
如果此类运算符的左操作数评估为逻辑 true
或非零,则不会评估右操作数。
所以在你的情况下:
z = ++x || ++y && ++z;
++x
正在计算 2
,使 x
等于 2
。这是非零的,所以右侧的所有内容都不会被评估,所以 y
和 z
不会递增。而z
是由逻辑OR
操作的结果赋值的,即1
。这就是你所看到的。
#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"或"lazy"运算。
如果此类运算符的左操作数评估为逻辑 true
或非零,则不会评估右操作数。
所以在你的情况下:
z = ++x || ++y && ++z;
++x
正在计算 2
,使 x
等于 2
。这是非零的,所以右侧的所有内容都不会被评估,所以 y
和 z
不会递增。而z
是由逻辑OR
操作的结果赋值的,即1
。这就是你所看到的。