{
int i = 1;
if (i++ && (i == 1))
printf("Yes\n");
else
printf("No\n");
}
根据我的理解,在if
条件中,首先评估表达式(i==1
),该表达式应该返回1
,然后在逻辑上对1
进行评估} i
的值,因此表达式应返回1 && 1 == 1
,但else
部分将被执行。
有人可以解释为什么else
部分被执行了吗?
答案 0 :(得分:92)
没有。在C中,&&
运算符的LHS评估和RHS的评估之间存在sequence point,并且必须在评估RHS之前完成增量并完成。因此,执行i++
(相当于i++ != 0
)并完成增量(并且表达式的计算结果为true),因此在评估RHS时,i == 2
因此总体表达是错误的,你打印出“否”。如果&&
运算符的LHS评估为false(0),则由于&&
运算符的“短路”属性,不会对RHS进行求值。
只有少数运营商具有在评估LHS和RHS之间具有序列点的属性:&&
,||
和,
(作为运营商,而不是参数列表中的分隔符) - 并且还有? :
,它不是二元运算符,但在评估条件之后和?
之后的表达式或之后的表达式之前有一个序列点:
被评估(其中一个或另一个,但不是两个,总是被评估)。
&&
和||
运算符是唯一具有“短路”属性的运算符。仅在LHS评估为真时评估&&
的RHS;只有在LHS评估为假的情况下才会评估||
的RHS。
Iwillnotexist Idonotexist正确asserted:
C11标准没有废除序列点,只有C ++ 11标准。
C ++ 11(ISO / IEC 14882:2011)说:
1.9程序执行
¶13在之前排序是由单个执行的评估之间的非对称,传递,成对关系 线程(1.10),它引起这些评估中的部分顺序。给定任何两个评估 A 和 B ,如果 A 在 B 之前排序,然后 A 的执行应先于 B 的执行。如果 A 之前没有排序 B 和 B 在 A 之前未排序,然后 A 和 B < EM>未测序。 [注意:执行未经检测的 评估可以重叠。 - 结束记录]评估 A 和 B 在 A 时 在 B 或 B 在 A 之前排序之前对其进行排序,但未指定哪个。 [注意:不确定 有序的评估不能重叠,但可以先执行。 - 结束记录]
术语'序列点'根本没有出现在C ++ 11中(唯一的近似匹配是'序列指针')。
C11(ISO / IEC 9899:2011)说:
5.1.2.3程序执行
¶3在之前排序是评估之间的不对称,传递,成对关系 由单个线程执行,这导致这些评估中的部分顺序。 鉴于任何两个评估 A 和 B ,如果 A 在 B 之前排序,则执行 A 的 应在执行 B 之前。 (相反,如果 A 在 B 之前排序,那么 B 是 在 A 之后排序。)如果 A 在 B 之前或之后没有排序,那么 A 和 B 是 未测序。当 A 排序时, A 和 B 的评估不确定地排序 在 B 之前或之后,但未指定哪个。 13) 序列点的存在 表达式 A 和 B 的评估之间意味着每个值计算和 在每次计算值和副作用之前,对与 A 相关的副作用进行排序 与 B 相关联。 (序列点的摘要见附件C.)
13)未经测序的评估的执行可以交错。不确定的顺序评估 不能交错,但可以按任何顺序执行。
因此,C11确实保留了序列点,但使用与C ++ 11基本相同的术语添加了“之前排序”和相关术语。
答案 1 :(得分:40)
这里有一个简单的解释
这就是为什么这种情况会变成'假'
答案 2 :(得分:28)
在表达式中使用&&
时,其参数保证从左到右进行评估。因此,i
在评估2
时将具有(i==1)
的值。因此,表达式为false,将执行else
部分。
但是,请注意完整性,如果左参数的计算结果为false或0,则根本不评估右参数。
答案 3 :(得分:1)
我认为1&amp;&amp; 1 = 1和1&amp; 0 = 0对您来说很清楚。 Michael L的回答对我来说似乎很好。但我仍然会尝试详细说明一下。 这是提供运算符优先级列表的链接:
http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm
如果您访问此链接并参考该表格,那么您就会知道&amp;&amp;从左到右相关性。首先我将在左边部分后变为2(Sruit试图用图表显示这个);然后在右边部分i == 1检查完成。我们可以通过写下面给出的代码来检查这个:
此代码解释了当执行流程达到i == 1 part时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&amp; 0 = 0。 我认为这很公平,可以理解。
答案 4 :(得分:0)
您很困惑,因为在循环语句中 i ++ 用于后期增量。 e.g。
for (i=0;i<1;i++)
在上面的循环程序中,i
将首先获得初始值并检查条件。 if
条件为真,因此它会增加 i 并将 i 评估为循环体的旧值,但在循环体外它具有新值 1 强>
在您的问题中,您正在使用if
并且i
的旧值范围将在遇到逻辑运算符时结束,它会自动获取新值并增加到 2 所以condition返回false。