为什么“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)执行的评估之间的不对称,传递,成对关系,这个关系在这些评估之间引发了偏序。 给定任何两个评估A和B ,如果A在B之前被sorting,那么A的执行应该在B的执行之前。 如果A在B之前未被测序, B在A之前未被测序,则A和B不被测序。 [ 注意:执行不确定的评估可能会重叠。 – 结束注释 ]当B或B在A之前进行测序之前,对A或B进行 测序时,评估A和B的测序是不确定 的 ,但未明确哪一个是未知的。 [ 注:不确定的测序评估不能重叠,但可以先执行。 – 结束注意 ]
“顺序点”一词根本不出现在C ++ 11中(唯一的近似匹配是“顺序指针”)。
C11(ISO / IEC 9899:2011)说:
5.1.2.3程序执行
¶3 之前sorting的是由单个线程执行的评估之间的不对称,传递,成对关系,这会在这些评估之间产生偏序。 给定任何两个评估A和B ,如果A在B之前被sorting,那么A的执行应该在B的执行之前。 (相反,如果A在B之前被测序,则B 在 A之后被测序 )。如果A在B之前或之后未被测序,则A和B不被测序。 当A在B之前或之后被测序时,评估A和B被不确定地测序 ,但未指定哪一个。 13)expression式A和B的评估之间的序列点的存在意味着在与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。