C编程语言中&&的行为

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

由于短路的评价,当x0,yz并不真正需要进行评估,因为0 && ANYTHING0.

一旦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求值falseB没有进行评估.

所以:

X成为0.&& ++y && ++z从那以后没有评估X/0/false && ...

y=0 由...分配 y = x/0/false

z由于++z没有被执行,因此保持不变.


koo*_*jah 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;  
} 
Run Code Online (Sandbox Code Playgroud)

你会得到的 x = 0, y = -1, z = -1, tmp = 0

左侧评估在C99标准中得到保证.你可以在这个部分找到它6.5.13 Logical AND operator

与按位二进制和运算符不同,&&运算符保证从左到右的评估; 在评估第一个操作数后有一个序列点.如果第一个操作数比较等于0,则不计算第二个操作数.

您可以在维基百科或C99标准的附录C中找到有关序列点的更多信息


Jac*_*ack 5

为了完整性(脑转储):

这种巫术背后的术语称为短路.让我们回顾一下您的代码,然后简要介绍一下为什么会发生这种情况.看着:

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,yz.它们被初始化为堆栈帧上的垃圾值,因为没有初始化(赋值运算符).这一行并不重要,现在让我们看看下一行:

 x = y = z = -1;
Run Code Online (Sandbox Code Playgroud)

......我们看到我们在同一条线上进行多项任务.回想一下,赋值运算符将使赋值运算符左侧的标识符变异(使用赋值运算符右侧的值)并返回值x.这称为赋值重载.但同样,这其实并不重要-实现了唯一重要的是x,yz现在所有-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 次

最近记录:

7 年,4 月 前