我在学习 C 语言中的逻辑运算符和条件时遇到了这个问题。
#include <stdio.h>
int main() {
int x = 3;
int y = 2;
int z = 3;
printf("Result #4 = %d\n", x++ <= 3 || y++ >= 2 && z++ != 3);
printf("x: %d y: %d z: %d\n", x, y, z);
return 0;
}
输出:
Result #4 = 1
x: 4 y: 2 z: 3
我不明白输出的最后一行。x、y、z 的值与我的理解不符。
以下是我的思路。
- 表达式 x++ <= 3 || y++ >= 2 && z++ != 3 将被评估为:x++ <= 3 || (y++ >= 2 && z++ != 3)。
- 然后,y++ >= 2 将为真并且 y 值将增加到 3。
- 然后,z++ != 3 将为假,并且 z 值将增加到 4。
- 由于整个条件为假,因此将评估 OR 条件的 RHS。
- 因此,x++ <= 3 将被评估为真,并且 x 将增加到 4。
- 整个条件将为真,因为 x++ <= 3 将被评估为真。
我试图找到这个问题的参考教科书或工作表,但没能找到。我在 StackOverflow 上做了一些研究,我不认为这是一种短路情况。如果是的话,我不明白为什么。
我能想到的唯一解释是,x 值将产生副作用(x 递增),因为它被评估为真,而 OR 语句的其余部分将不会产生副作用,因为它被评估为假,因此 y 和 z 不会递增。是这样吗?
如果你用括号来思考,那么为什么只在右侧应用它们,而不在另一侧应用它们呢?表达式的求值方式应该是这样的
(x++ <= 3) || (y++ >= 2 && z++ != 3)
。为什么假设首先评估右侧?相等部分是从左到右评估的。
int x = 3
首先对andx++ <= 3
进行求值:3 <= 3
为真并x
得到 4。不对右边进行求值,y
保留z
其初始值。你写得对
现在我们来阅读一下 C 标准中有关逻辑或运算符的内容(C23 标准,6.5.14 逻辑或运算符):
因此,当第一个操作数即表达式的
x++ <= 3
计算结果为逻辑真(其结果等于 1)时,第二个操作数(y++ >= 2 && z++ != 3)
不计算结果。这意味着变量y
和z
保持不变。注意(6.5.8 关系运算符):
其次(6.5.2.4 后缀增量和减量运算符):
x
即在逻辑或运算符的第一个操作数中,将增量前的变量值3
与整型常量进行比较3
,并在下一条printf
语句中输出已经增量的变量x
。这个表达式的求值方式如下: