C增量运算符
我已经在代码块中编译了下面的代码,它显示了输出0…0。但是我认为它的输出应该是0…1,因为这里的“if”语句不是真的,所以“if”后面的语句不会被执行。然后j增加1(因为“if”语句中的j++),但我仍然是0。最后一个printf()应该是0…1C增量运算符,c,short-circuiting,post-increment,C,Short Circuiting,Post Increment,我已经在代码块中编译了下面的代码,它显示了输出0…0。但是我认为它的输出应该是0…1,因为这里的“if”语句不是真的,所以“if”后面的语句不会被执行。然后j增加1(因为“if”语句中的j++),但我仍然是0。最后一个printf()应该是0…1 #include <stdio.h> int main() { int i =0,j=0; if(i && j++) printf("%d..%d\n",i++,j); printf
#include <stdio.h>
int main()
{
int i =0,j=0;
if(i && j++)
printf("%d..%d\n",i++,j);
printf("%d...%d",i,j);
return 0;
}
#包括
int main()
{
int i=0,j=0;
if(i&&j++)
printf(“%d..%d\n”,i++,j);
printf(“%d..%d”,i,j);
返回0;
}
条件的第一部分(i
)已经为假,因此第二部分(j++
)不会执行。条件的第一部分(i
)已经为假,因此第二部分(j++
)不会执行。因为i
是0
(falsy),没有理由执行j++
。这叫短路
它在检查
if(a
时很有用,因为i
是0
(falsy),所以没有理由执行j++
。这叫短路
它在检查
if(a您将无法递增j
。请看您的if声明:
if(i && j++)
仅当i
和j
均为真时,才执行if块。但是由于i
已经为false,因此甚至不需要检查j++
。它也被称为。您将无法获得递增的j
。请看您的if声明:
if(i && j++)
仅当i
和j
均为真时,才执行if块。但是由于i
已经为false,因此甚至不需要检查j++
。它也被称为。在if条件中,对j的增量没有被应用的原因是因为表达式被短路了,也就是说,i从来都不是非零,因此,不需要计算第二个表达式。在if条件中,对j的增量没有被应用的原因是因为该表达式被短路了——即,i从来都不是非零的,因此不需要计算第二个表达式。使用按位and和&
而不是使用逻辑and和,只要i
和j
是0
或1
,它就不会短路,也不会以您想要的方式工作:
...
if(i & j++)
printf("%d..%d\n",i++,j);
或者如果他们不是:
if (!!i & !!(j++))
...
不要使用逻辑and和&
,而是使用按位and和&
,只要i和j和0或1
,它们就不会短路,也不会按您想要的方式工作:
...
if(i & j++)
printf("%d..%d\n",i++,j);
或者如果他们不是:
if (!!i & !!(j++))
...
参见C11 6.5.13逻辑与运算符p4(我的重点)
与按位二进制&运算符不同,&&运算符保证
从左到右评价;如果对第二个操作数求值,则
第一次和第二次评估之间的序列点
操作数如果第一个操作数比较等于0,则第二个操作数
未计算操作数。
示例中的第一个操作数是i
。它比较等于0,因此不计算(执行)第二个操作数(j++
)。因此,您稍后的printf
显示j
仍然为0是正确的。参见C11 6.5.13逻辑与运算符p4(我的重点)
与按位二进制&运算符不同,&&运算符保证
从左到右评价;如果对第二个操作数求值,则
第一次和第二次评估之间的序列点
操作数如果第一个操作数比较等于0,则第二个操作数
未计算操作数。
示例中的第一个操作数是i
。它比较等于0,因此不计算(执行)第二个操作数(j++
)。因此,后面的printf
显示j
仍然为0是正确的。由于第一个条件i
(和&
运算符的左侧)的求值已经返回false,因此没有执行j++
表达式,因此第二个条件j++
的求值是不正确的
这是编译器进行的常见优化,通常称为短路条件评估,在某些编译器中,您可以关闭此优化,以避免此类副作用。由于第一个条件的评估i
(&&
运算符的左侧)已返回false,因此第二个条件j++
不会被计算
这是编译器进行的一种常见优化,通常称为短路条件评估。在某些编译器中,您可以关闭此优化,以避免此类副作用。正如您在本示例代码中看到的,来自源代码
第二,如果未执行:
movl i(%rip), %eax
testl %eax, %eax ; <-- if i
je .L2
movl j(%rip), %eax
testl %eax, %eax ; <-- if j Not EXECUTED !!!
setne %dl
addl $1, %eax ; <-- j++
movl %eax, j(%rip)
testb %dl, %dl
je .L2
... ; inner IF
.j2
movli(%rip),%eax
testl%eax,%eax;正如您在本示例代码中看到的,来自您的源代码
第二,如果未执行:
movl i(%rip), %eax
testl %eax, %eax ; <-- if i
je .L2
movl j(%rip), %eax
testl %eax, %eax ; <-- if j Not EXECUTED !!!
setne %dl
addl $1, %eax ; <-- j++
movl %eax, j(%rip)
testb %dl, %dl
je .L2
... ; inner IF
.j2
movli(%rip),%eax
testl%eax,%eax;正如您提到的,if语句为false则为true。
但我相信所使用的概念/逻辑是不恰当的,原因如下
在此之前,让我们了解&&(逻辑AND)运算符的工作原理。
If表示如果与其关联的两个操作数都为true,则只有结果为true。
注:1.对于编译器,这意味着如果任何一个操作数为false,编译器将不会进一步计算,即跳到下一个有效代码行。
编程时,2.0(零)状态为false
那么,
编译器首先搜索运算符,然后查找
与之相关的
因此,一旦编译器遇到“&&”,它就会将操作符的左侧视为
&&(逻辑AND)的关联性从左到右,并计算左侧操作数的值