为什么“if(i ++ &&(i == 1))”false其中我是一个int值保持1?

{ int i = 1; if (i++ && (i == 1)) printf("Yes\n"); else printf("No\n"); } 

根据我的理解,在if条件中,首先expression式( i==1 )将被评估,它应该返回1 ,然后在逻辑上与1作为i的值,所以expression式应该返回1 && 1 == 1 ,但是else部分被执行。

有人可以解释为什么else部分被执行吗?

在C中, &&操作者的LHS评估与RHS评估之间存在一个顺序点 ,并且在RHS评估之前必须发生并且完成增量。 所以, i++ (相当于i++ != 0 )被执行,增量完成(expression式计算结果为真),所以在RHS被评估的时候, i == 2 ,因此整体expression式是错误的,打印“不”。 如果&&操作符的LHS评估为错误(0),则由于&&操作符的“短路”属性,RHS将不会被评估。

在LHS和RHS的评估之间,只有less数操作者具有序列点的属性: &&|| ,(作为操作员,而不是作为参数列表中的分隔符) – 还有? : ? :也不是一个二元运算符,而是在条件被评估之后和之后的expression式之前有一个序列点? 或评估后的expression式(总是评估哪一个或哪一个,但不是两个)。

&&|| 运营商是唯一拥有“短路”属性的运营商。 &&的RHS只在LHS评估为真时评估; ||的RHS 仅在LHS评估为假时才被评估。


澄清序列点

Iwillnotexist Idonotexist正确地声称 :

C11标准没有排除序列点,只有C ++ 11标准。

C ++ 11(ISO / IEC 14882:2011)说:

1.9程序执行

¶13 之前sorting的是一个由单个线程(1.10)执行的评估之间的不对称,传递,成对关系,这个关系在这些评估之间引发了偏序。 给定任何两个评估AB ,如果AB之前被sorting,那么A的执行应该在B的执行之前。 如果AB之前未被测序, BA之前未被测序,则AB不被测序。 [ 注意:执行不确定的评估可能会重叠。 – 结束注释 ]当BBA之前进行测序之前,对AB进行 测序时,评估AB测序不确定 ,但未明确哪一个是未知的。 [ 注:不确定的测序评估不能重叠,但可以先执行。 – 结束注意 ]

“顺序点”一词根本不出现在C ++ 11中(唯一的近似匹配是“顺序指针”)。

C11(ISO / IEC 9899:2011)说:

5.1.2.3程序执行

¶3 之前sorting的是由单个线程执行的评估之间的不对称,传递,成对关系,这会在这些评估之间产生偏序。 给定任何两个评估AB ,如果AB之前被sorting,那么A的执行应该在B的执行之前。 (相反,如果AB之前被测序,则B A之后被测序 )。如果AB之前或之后未被测序,则AB不被测序。 当AB之前或之后被测序时,评估AB不确定地测序 ,但未指定哪一个。 13)expression式AB的评估之间的序列点的存在意味着B有关的每个值计算和副作用之前,与A有关的每个值计算和副作用被sorting。 (附件C给出了顺序点的摘要。)

13)不确定评估的执行可以交错。 不确定的测序评估不能交错,但可以按任何顺序执行。

因此,C11确实保留了序列点,但是使用与C ++ 11基本相同的术语添加了“之前测序”和相关术语。

在这里,一个简单的解释

在这里输入图像说明

这就是为什么这个条件变成'假'

当在expression式中使用&& ,其参数保证从左到右进行评估 。 所以当(i==1)被评估的时候, i会得到2的值。 因此,expression式是错误的, else部分将被执行。

但是,请注意完整性,如果左参数计算结果为false或0,则根本不评估正确的参数。

我认为1 && 1 = 1和1 && 0 = 0对你来说很清楚。 迈克尔L的回答对我来说似乎很好。但是我仍然会试着详细阐述一下。 这里是提供运算符优先级列表的链接:

http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm

如果你访问这个链接并引用这个表,那么你将会知道&&从左到右的结合性。所以首先我会变成2之后的左边部分(Sruit试图用这个图表示);然后对于右边部分我== 1检查完成。我们可以通过编写如下所示的代码来检查:

这段代码解释了当执行stream程到达i == 1部分时,i = 2。

 #include <stdio.h> int main() { int i = 1; if (i++ && (printf("%d\n",i))) printf("Yes\n"); else printf("No\n"); return 0; } 

所以输出是:

2

所以2 == 1出来是错误的,最终答案给出了令人惊讶的感觉! 右边括号给出0和左边1如此1 && 0 = 0。 我认为这是理所当然的。

你很困惑,因为在循环语句我++是用于后增量。 例如

 for (i=0;i<1;i++) 

在上面的循环程序中, i将首先获得初始值和检查条件。 if条件是真的,所以它递增并评估为循环体的旧值,但在循环体外它有新的值1

在你的问题中,你使用的是if和旧的价值范围i将结束当它遇到逻辑运算符它会自动获得新的价值和增量到2,所以条件返回false。