用C语言编写&&的行为

时间:2022-09-19 16:05:18

I am beginner in C programming language, recently I have read about Logical AND && operator.

我是C编程语言的初学者,最近我读到了关于逻辑和&& &算符的知识。

I also know that, in C programming language all non-zero values are treated as TRUE.

我也知道,在C编程语言中,所有非零值都被当作是真的。

NON-ZERO && NON-ZERO = 1  
NON-ZERO && ZERO = 0  
ZERO && NON-ZERO = 0
ZERO && ZERO = 0  

But when I am dealing with the following program then I am not getting expected answer.

但是当我处理下面的程序时,我不会得到预期的答案。

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;  
} 

I am expecting

我在等

x = 0, y = 0, z = 0 

but the answer is

但答案是

x = 0, y = 0, z = -1

Can anyone please explain, Why I am getting this answer?

谁能解释一下,我为什么得到这个答案?

5 个解决方案

#1


21  

Because of Short-circuit evaluation, when x is 0, y and z don't really need to be evaluated since 0 && ANYTHING is 0.

由于短路评估,当x = 0时,y和z不需要从0开始求值,任何值都是0。

Once x is incremented to 0, the result is 0, and that's what y gets.

一旦x增加到0,结果是0,这就是y的值。

z remains unchanged (-1).

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;

#2


14  

I only can think about that && evaluates in short circuit: given A && B, if A evaluates false then B is not evaluated.

我只能在短路情况下考虑&&评估:给定A & B,如果A评估为false,那么B就不被评估。

So:

所以:

X becomes 0. && ++y && ++z does not evaluates since X/0/false && ...

X变成0。因为X/0/false && & +z没有计算值。

y=0 as assigned from y = x/0/false

根据y= x/0/false, y=0

z remains unmodified since ++z does not get executed.

z没有被修改,因为++z没有被执行。

#3


5  

What happens is that ++y and ++z are never evaluated because the first part already ensures what the new value of y will be.

结果是+y +z永远不会被求值因为第一部分已经确定了y的新值。

The first part of your statement is ++x && ... which is equivalent to 0 && ... and then we already know that y will be 0 in the end so the rest of the statement is not executed.

你陈述的第一部分是++x && &…等于0和&…然后我们已经知道y最后是0所以语句的其余部分没有执行。

if you did this:

如果你这样做:

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;  
} 

You would get x = 0, y = -1, z = -1, tmp = 0

得到x = 0 y = -1 z = -1 tmp = 0

The left evaluation is guaranteed in the C99 standard. You can find it in the section 6.5.13 Logical AND operator

在C99标准中保证左评价。您可以在6.5.13节逻辑和运算符中找到它

Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation; there is a sequence point after the evaluation of the first operand. If the first operand compares equal to 0, the second operand is not evaluated.

与位二进制与运算符不同,&运算符保证从左到右的运算;第一个操作数求值后,有一个序列点。如果第一个操作数比较为0,则不计算第二个操作数。

You can find more information about what is a sequence point on Wikipedia or in the Annex C of the C99 standard

您可以在*或C99标准的附录C中找到关于序列点的更多信息

#4


5  

For completeness (brain dump):

出于完整性的考虑(大脑转储):

The term behind this sorcery is called short circuiting. Let's go over your code and then a brief blurb about why this happens. Looking at:

这个巫术背后的术语叫做短路。让我们先看一下代码,然后简要介绍一下为什么会发生这种情况。看:

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;  
}

... we begin to break it down line by line. The first line:

…我们开始逐行分解它。第一行:

int x, y, z;

... declares three integers, x, y and z. They are initialized to garbage values on the stack frame because there is no initialization (assignment operator). This line does not really matter, now let's look at the next one:

…声明三个整数x、y和z。由于没有初始化(赋值操作符),它们被初始化为堆栈帧上的垃圾值。这条线并不重要,现在我们来看下一条:

 x = y = z = -1;

... we see that we are doing multiple assignments on the same line. Recall that the assignment operator will mutate the identifier to the left of the assignment operator (using the value to the right of the assignment operator) and return the value of x. This is known as assignment overloading. But again, this does not really matter -- the only important thing to realize is x, y and z are now all -1. Let's look at the next line:

…我们看到我们在同一条线上做了多个作业。回想一下,赋值操作符会将标识符修改为赋值操作符的左边(使用赋值操作符右边的值),并返回x的值,这被称为赋值重载。但同样,这并不重要,唯一需要注意的是x y z都是-1。让我们看下一行:

 y = ++x && ++y && ++z;

... Sorcery Yoda says. Let's add the parenthesis to make it more obvious which step is being evaluated first:

…巫术尤达说。让我们添加括号,使它更明显,哪个步骤是首先被评估的:

 y = ( ( ++x ) && ++y && ++z );

... now looking at the inner-most parenthesis we see that it's a prefix increment of x, meaning we will increment the value of x and then return it. We note that x is originally -1 and it is now 0 after being incremented. This will resolve as follows:

…现在看一下最里面的括号,我们看到它是x的前缀增量,意味着我们将增加x的值然后返回它。我们注意到x原来是-1,现在它是0。这将解决下列问题:

 y = ( 0 && ++y && ++z );

... now it's important to note that looking at our truth tables:

…现在很重要的一点是,看看我们的真值表:

A | B | A && B
--------------
T | T |   T
T | F |   F
F | T |   F
F | F |   F

... for the AND logical operator we see that both F (AND) T, T (AND) F are F. The compiler realizes this and short circuits when ever it is evaluating a conjunction (AND) where a value is false -- a clever technique of optimization. It will then resolve to assigning y to be 0 (which is false). Recall that in C any non-zero value is true, only 0 is false. The line will look as follows:

…对于和逻辑运算符,我们看到F(和)T(和)F都是F。编译器在计算一个值为false的连接(和)时实现了这个和短路——这是一种巧妙的优化技术。然后它将解析出y为0(这是错误的)。回想一下,在C中任何非零值都为真,只有0为假。这条线将如下所示:

 y = 0;

... now looking at the next line:

…现在看下一行:

 printf( "x = %d, y = %d, z = %d, x, y, z );

... it should be obvious to you now that it will output x = 0, y = 0, z = -1.

…很明显,它会输出x = 0 y = 0 z = -1。

#5


4  

&& operator is evaluated pairwise, therefore I'm guessing C is evaluating

&&算符是成对的,所以我猜C是对的

((++x && ++y) && ++z)

now, ++x will return zero therefore the first && will fail as will the second one without the need to evaluate ++y or ++z.

现在,++x将返回0,因此第一个&和将失败,第二个也将失败,而不需要计算+y或+z。

y = 0 since that is the result of the expression.

y = 0,因为这是表达式的结果。

z is not touched

z不是感动

#1


21  

Because of Short-circuit evaluation, when x is 0, y and z don't really need to be evaluated since 0 && ANYTHING is 0.

由于短路评估,当x = 0时,y和z不需要从0开始求值,任何值都是0。

Once x is incremented to 0, the result is 0, and that's what y gets.

一旦x增加到0,结果是0,这就是y的值。

z remains unchanged (-1).

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;

#2


14  

I only can think about that && evaluates in short circuit: given A && B, if A evaluates false then B is not evaluated.

我只能在短路情况下考虑&&评估:给定A & B,如果A评估为false,那么B就不被评估。

So:

所以:

X becomes 0. && ++y && ++z does not evaluates since X/0/false && ...

X变成0。因为X/0/false && & +z没有计算值。

y=0 as assigned from y = x/0/false

根据y= x/0/false, y=0

z remains unmodified since ++z does not get executed.

z没有被修改,因为++z没有被执行。

#3


5  

What happens is that ++y and ++z are never evaluated because the first part already ensures what the new value of y will be.

结果是+y +z永远不会被求值因为第一部分已经确定了y的新值。

The first part of your statement is ++x && ... which is equivalent to 0 && ... and then we already know that y will be 0 in the end so the rest of the statement is not executed.

你陈述的第一部分是++x && &…等于0和&…然后我们已经知道y最后是0所以语句的其余部分没有执行。

if you did this:

如果你这样做:

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;  
} 

You would get x = 0, y = -1, z = -1, tmp = 0

得到x = 0 y = -1 z = -1 tmp = 0

The left evaluation is guaranteed in the C99 standard. You can find it in the section 6.5.13 Logical AND operator

在C99标准中保证左评价。您可以在6.5.13节逻辑和运算符中找到它

Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation; there is a sequence point after the evaluation of the first operand. If the first operand compares equal to 0, the second operand is not evaluated.

与位二进制与运算符不同,&运算符保证从左到右的运算;第一个操作数求值后,有一个序列点。如果第一个操作数比较为0,则不计算第二个操作数。

You can find more information about what is a sequence point on Wikipedia or in the Annex C of the C99 standard

您可以在*或C99标准的附录C中找到关于序列点的更多信息

#4


5  

For completeness (brain dump):

出于完整性的考虑(大脑转储):

The term behind this sorcery is called short circuiting. Let's go over your code and then a brief blurb about why this happens. Looking at:

这个巫术背后的术语叫做短路。让我们先看一下代码,然后简要介绍一下为什么会发生这种情况。看:

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;  
}

... we begin to break it down line by line. The first line:

…我们开始逐行分解它。第一行:

int x, y, z;

... declares three integers, x, y and z. They are initialized to garbage values on the stack frame because there is no initialization (assignment operator). This line does not really matter, now let's look at the next one:

…声明三个整数x、y和z。由于没有初始化(赋值操作符),它们被初始化为堆栈帧上的垃圾值。这条线并不重要,现在我们来看下一条:

 x = y = z = -1;

... we see that we are doing multiple assignments on the same line. Recall that the assignment operator will mutate the identifier to the left of the assignment operator (using the value to the right of the assignment operator) and return the value of x. This is known as assignment overloading. But again, this does not really matter -- the only important thing to realize is x, y and z are now all -1. Let's look at the next line:

…我们看到我们在同一条线上做了多个作业。回想一下,赋值操作符会将标识符修改为赋值操作符的左边(使用赋值操作符右边的值),并返回x的值,这被称为赋值重载。但同样,这并不重要,唯一需要注意的是x y z都是-1。让我们看下一行:

 y = ++x && ++y && ++z;

... Sorcery Yoda says. Let's add the parenthesis to make it more obvious which step is being evaluated first:

…巫术尤达说。让我们添加括号,使它更明显,哪个步骤是首先被评估的:

 y = ( ( ++x ) && ++y && ++z );

... now looking at the inner-most parenthesis we see that it's a prefix increment of x, meaning we will increment the value of x and then return it. We note that x is originally -1 and it is now 0 after being incremented. This will resolve as follows:

…现在看一下最里面的括号,我们看到它是x的前缀增量,意味着我们将增加x的值然后返回它。我们注意到x原来是-1,现在它是0。这将解决下列问题:

 y = ( 0 && ++y && ++z );

... now it's important to note that looking at our truth tables:

…现在很重要的一点是,看看我们的真值表:

A | B | A && B
--------------
T | T |   T
T | F |   F
F | T |   F
F | F |   F

... for the AND logical operator we see that both F (AND) T, T (AND) F are F. The compiler realizes this and short circuits when ever it is evaluating a conjunction (AND) where a value is false -- a clever technique of optimization. It will then resolve to assigning y to be 0 (which is false). Recall that in C any non-zero value is true, only 0 is false. The line will look as follows:

…对于和逻辑运算符,我们看到F(和)T(和)F都是F。编译器在计算一个值为false的连接(和)时实现了这个和短路——这是一种巧妙的优化技术。然后它将解析出y为0(这是错误的)。回想一下,在C中任何非零值都为真,只有0为假。这条线将如下所示:

 y = 0;

... now looking at the next line:

…现在看下一行:

 printf( "x = %d, y = %d, z = %d, x, y, z );

... it should be obvious to you now that it will output x = 0, y = 0, z = -1.

…很明显,它会输出x = 0 y = 0 z = -1。

#5


4  

&& operator is evaluated pairwise, therefore I'm guessing C is evaluating

&&算符是成对的,所以我猜C是对的

((++x && ++y) && ++z)

now, ++x will return zero therefore the first && will fail as will the second one without the need to evaluate ++y or ++z.

现在,++x将返回0,因此第一个&和将失败,第二个也将失败,而不需要计算+y或+z。

y = 0 since that is the result of the expression.

y = 0,因为这是表达式的结果。

z is not touched

z不是感动