May*_*ari 22 c operators logical-operators
我是C编程语言的初学者,最近我读过有关Logical AND &&运算符的内容.
我也知道,在C编程语言中,所有非零值都被视为TRUE.
NON-ZERO && NON-ZERO = 1
NON-ZERO && ZERO = 0
ZERO && NON-ZERO = 0
ZERO && ZERO = 0
Run Code Online (Sandbox Code Playgroud)
但是当我处理以下程序时,我没有得到预期的答案.
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;
}
Run Code Online (Sandbox Code Playgroud)
我期待着
x = 0, y = 0, z = 0
Run Code Online (Sandbox Code Playgroud)
但答案是
x = 0, y = 0, z = -1
Run Code Online (Sandbox Code Playgroud)
任何人都可以解释一下,为什么我得到这个答案?
编辑:在这个问题中,我没有询问运营商的优先级.
Mar*_*oun 21
由于短路的评价,当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;
Run Code Online (Sandbox Code Playgroud)
Alf*_*awa 14
我只能想到这一点&&在评估短路:给定的A && B,如果A求值false则B没有进行评估.
所以:
X成为0.&& ++y && ++z从那以后没有评估X/0/false && ...
y=0 由...分配 y = x/0/false
z由于++z没有被执行,因此保持不变.
会发生什么++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;
}
Run Code Online (Sandbox Code Playgroud)
你会得到的 x = 0, y = -1, z = -1, tmp = 0
左侧评估在C99标准中得到保证.你可以在这个部分找到它6.5.13 Logical AND operator
与按位二进制和运算符不同,&&运算符保证从左到右的评估; 在评估第一个操作数后有一个序列点.如果第一个操作数比较等于0,则不计算第二个操作数.
您可以在维基百科或C99标准的附录C中找到有关序列点的更多信息
为了完整性(脑转储):
这种巫术背后的术语称为短路.让我们回顾一下您的代码,然后简要介绍一下为什么会发生这种情况.看着:
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;
}
Run Code Online (Sandbox Code Playgroud)
......我们开始逐行分解.第一行:
int x, y, z;
Run Code Online (Sandbox Code Playgroud)
...声明三个整数x,y和z.它们被初始化为堆栈帧上的垃圾值,因为没有初始化(赋值运算符).这一行并不重要,现在让我们看看下一行:
x = y = z = -1;
Run Code Online (Sandbox Code Playgroud)
......我们看到我们在同一条线上进行多项任务.回想一下,赋值运算符将使赋值运算符左侧的标识符变异(使用赋值运算符右侧的值)并返回值x.这称为赋值重载.但同样,这其实并不重要-实现了唯一重要的是x,y和z现在所有-1.我们来看下一行:
y = ++x && ++y && ++z;
Run Code Online (Sandbox Code Playgroud)
...魔法尤达说.让我们添加括号,以便更明显地首先评估哪个步骤:
y = ( ( ++x ) && ++y && ++z );
Run Code Online (Sandbox Code Playgroud)
...现在查看最里面的括号,我们看到它是一个前缀增量x,意味着我们将增加值,x然后返回它.我们注意到它x最初为-1,并且在递增后现在为0.这将解决如下:
y = ( 0 && ++y && ++z );
Run Code Online (Sandbox Code Playgroud)
......现在重要的是要注意查看我们的真值表:
A | B | A && B
--------------
T | T | T
T | F | F
F | T | F
F | F | F
Run Code Online (Sandbox Code Playgroud)
...对于AND逻辑运算符,我们看到F(AND)T,T(AND)F都是F.编译器在评估一个值为的连接(AND)时实现这个和短路false- 一个聪明的人优化技术.然后它将解析为分配y为0(这是假的).回想一下,在C中任何非零值都是true,只有0 false.该行将如下所示:
y = 0;
Run Code Online (Sandbox Code Playgroud)
......现在看下一行:
printf( "x = %d, y = %d, z = %d, x, y, z );
Run Code Online (Sandbox Code Playgroud)
......现在你应该明白它会输出x = 0, y = 0, z = -1.
| 归档时间: |
|
| 查看次数: |
9764 次 |
| 最近记录: |