我是C编程语言的初学者,最近我读过有关Logical AND &&
运算符的内容。
我也知道,在C编程语言中,所有非零值都被视为 TRUE 。
NON-ZERO && NON-ZERO = 1
NON-ZERO && ZERO = 0
ZERO && NON-ZERO = 0
ZERO && ZERO = 0
但是当我处理以下程序时,我没有得到预期的答案。
int main(){
int x, y, z;
x = y = z = -1;
y = ++x && ++y && ++z;
printf("x = %d, y = %d, z = %d, x, y, z);
return 0;
}
我期待
x = 0, y = 0, z = 0
但答案是
x = 0, y = 0, z = -1
任何人都可以解释一下,为什么我得到这个答案?
编辑: 在这个问题中,我没有询问运营商的优先级。
答案 0 :(得分:21)
由于Short-circuit evaluation,当x
为0
时,y
和z
并不需要进行评估,因为0 && ANYTHING
是0
。
x
增加到0
后,结果为0
,这就是y
得到的结果。
z
保持不变(-1
)。
x | y | z
----+----+-----
-1 | -1 | -1 //x = y = z = -1;
0 | -1 | -1 //++x && ... Now the whole expression is evaluated to 0
0 | 0 | -1 //y = ++x && ++y && ++z;
答案 1 :(得分:14)
我只能考虑&&
评估短路:给定A && B
,如果A
评估false
,则{{1} }未被评估。
所以:
B
变为X
。自0
&& ++y && ++z
未进行评估
从X/0/false && ...
分配的 y=0
y = x/0/false
未经修改,因为z
未执行。
答案 2 :(得分:5)
由于第一部分已经确定了++y
的新值,因此永远不会评估++z
和y
。
你的陈述的第一部分是++x && ...
,它相当于0 && ...
然后我们已经知道y
最后会是0,所以其余的陈述都没有被执行
如果你这样做:
int main(){
int x,y,z,tmp;
x = y = z = -1;
tmp = ++x && ++y && ++z;
printf("x = %d, y = %d, z = %d, tmp = %d", x,y,z, tmp);
return 0;
}
你会得到x = 0, y = -1, z = -1, tmp = 0
左边评估在C99标准中得到保证。您可以在6.5.13 Logical AND operator
与按位二进制&操作员,&&运营商保证从左到右的评估; 在评估第一个操作数后有一个序列点。如果是第一个操作数 比较等于0,不评估第二个操作数。
您可以在Wikipedia或C99标准的附录C中找到有关序列点的更多信息
答案 3 :(得分:5)
为了完整性(脑转储):
这个巫术背后的术语叫做short circuiting。让我们回顾一下您的代码,然后简要介绍一下为什么会发生这种情况。看着:
int main( void ) {
int x, y, z;
x = y = z = -1;
y = ++x && ++y && ++z;
printf( "x = %d, y = %d, z = %d, x, y, z );
return 0;
}
......我们开始逐行分解。第一行:
int x, y, z;
...声明三个整数,x
,y
和z
。它们被初始化为堆栈帧上的垃圾值,因为没有初始化(赋值运算符)。这一行并不重要,现在让我们看看下一行:
x = y = z = -1;
......我们看到我们在同一条线上进行多项任务。回想一下,赋值运算符将使赋值运算符左侧的标识符变异(使用赋值运算符右侧的值)并返回x
的值。这称为赋值重载。但同样,这并不重要 - 要实现的唯一重要事项是x
,y
和z
现在都是-1。我们来看下一行:
y = ++x && ++y && ++z;
...魔法尤达说。让我们添加括号,以便更明显地首先评估哪个步骤:
y = ( ( ++x ) && ++y && ++z );
...现在查看最里面的括号,我们看到它是x
的前缀增量,这意味着我们将增加x
的值然后返回它。我们注意到x
最初为-1,并且在递增后现在为0。这将解决如下:
y = ( 0 && ++y && ++z );
...现在重要的是要注意查看我们的真值表:
A | B | A && B
--------------
T | T | T
T | F | F
F | T | F
F | F | F
...对于AND
逻辑运算符,我们看到F(AND)T,T(AND)F都是F.编译器在评估连接(AND)时实现了这个和短路其中值为false
- 一种聪明的优化技术。然后它将解析为将y
指定为0(这是假的)。回想一下,在C中,任何非零值都是true
,只有0是false
。该行将如下所示:
y = 0;
...现在看下一行:
printf( "x = %d, y = %d, z = %d, x, y, z );
...现在应该很明显它会输出x = 0, y = 0, z = -1
。
答案 4 :(得分:4)
&&
运算符是成对计算的,因此我猜C正在评估
((++x && ++y) && ++z)
现在,++x
将返回零,因此第一个&&
将失败,而第二个++y
将失败,而无需评估++z
或y = 0
。
z
因为这是表达式的结果。
{{1}}未被触及