{
int i = 1;
if (i++ && (i == 1))
printf("Yes\n");
else
printf("No\n");
}
依据我的理解,在if
条件语句中,首先会对表达式(i==1
)进行求值,其应该返回1
,然后将其与i
的值即1
逻辑上做与运算,所以表达式应该返回1 && 1 == 1
,但实际上执行了else
部分。请问有人能解释一下为什么会执行else
部分吗?{
int i = 1;
if (i++ && (i == 1))
printf("Yes\n");
else
printf("No\n");
}
依据我的理解,在if
条件语句中,首先会对表达式(i==1
)进行求值,其应该返回1
,然后将其与i
的值即1
逻辑上做与运算,所以表达式应该返回1 && 1 == 1
,但实际上执行了else
部分。请问有人能解释一下为什么会执行else
部分吗?在C语言中,&&
运算符的左侧和右侧有一个序列点,而且必须在右侧被评估之前执行并完成增量。因此,i++
(相当于i++ != 0
)被执行并完成增量(表达式评估为true),所以在右侧被评估时,i == 2
,因此整个表达式为false,你会看到打印出'No'。如果&&
运算符的左侧评估为false(0),则由于&&
运算符的“短路”属性,右侧不会被评估。
&&
、||
和,
(作为运算符,而不是在参数列表中作为分隔符)- 还有? :
,它不是二元运算符,但在条件评估后和?
后面的表达式或:
后面的表达式之前有一个序列点被评估(其中一个被评估,但不是两者都被评估)。
&&
和||
运算符是唯一具有“短路”属性的运算符。当LHS评估为真时,仅评估&&
的RHS;当LHS评估为假时,仅评估||
的RHS。
我不会存在 我不存在正确地断言:
C11标准并没有取消序列点,只有C++11标准这样做了。
C++11(ISO/IEC 14882:2011)说:
1.9 程序执行¶13 Sequenced before 是单个线程(1.10)执行的评估之间的一种非对称、传递性、成对关系,它在这些评估之间引入了一个偏序关系。给定任意两个评估 A 和 B,如果 A 在 B 之前被排序,则 A 的执行应该在 B 的执行之前。如果 A 不在 B 之前排序,且 B 不在 A 之前排序,则 A 和 B 是 unsequenced。(注意:未排序评估的执行可能重叠。—注释结束)当 A 在 B 之前排序或者 B 在 A 之前排序时,评估 A 和 B 是 indeterminately sequenced,但是不确定哪个先执行。(注意:不确定顺序的评估不能重叠,但是任何一个都可以先执行。—注释结束)
术语“sequence point”在C++11中根本没有出现(唯一接近的匹配项是“sequence pointer”)。
C11(ISO/IEC 9899:2011)如下所述:
5.1.2.3 程序执行因此,C11保留了序列点,但使用与C++11基本相同的术语添加了“顺序前”和相关术语。
((i == 1) && i++)
,将会打印出 Yes
。 - Bhargav Rao?:
的序列点仅在其第一个操作数(即条件)评估后立即保证一次,没有其他情况。 - Grzegorz Szpetkowski&
运算符不同,&&
运算符保证从左到右进行评估;如果评估第二个操作数,则在评估第一个和第二个操作数之间存在序列点。如果第一个操作数等于0,则不评估第二个操作数。(强调添加) - Iwillnotexist Idonotexist这里是一个简单的解释
这就是为什么这个条件变成了“false”
if (i++ & (i == 1)) [...]
(注意单个和号)会产生不同的结果,但是你的回答没有提到任何概念,帮助某人弄清楚为什么会这样。 - David Richerby&&
时,其参数保证从左到右进行评估。因此,当评估(i==1)
时,i
将具有值2
。因此,该表达式为假,将执行else
部分。http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm
如果您访问此链接并参考该表,则会知道&&具有从左到右的结合性。因此,在左部分(Sruit试图使用图表来展示)之后,首先我将变为2;然后对于右侧部分,将进行i==1检查。我们可以通过编写以下类似的代码来检查:#include <stdio.h>
int main() {
int i = 1;
if (i++ && (printf("%d\n",i)))
printf("Yes\n");
else
printf("No\n");
return 0;
}
所以2==1最终得出的结果是false,这让人感到惊讶! 右侧括号给出0,左侧括号给出1,所以1&&0=0。 我认为这已经足够理解了。2
是的
for (i=0;i<1;i++)
i
首先获取初始值并检查条件。由于 if
条件为真,因此它会将 i 递增,并将 i 评估为循环体的旧值,但在循环体外部,它具有新值 1。if
,而 i
的旧值作用域将在遇到逻辑运算符时结束,它会自动获取新值并递增为 2,因此条件返回 false。
i == 1
周围加上括号。 - Pete Beckeri == 1
先被评估,因为你有一些期望括号中的事情先发生。但实际上不是这样的;括号与评估顺序无关,它们只控制参数分组。 - user2357112&
)。它将检查第一个参数,如果它为false
(或 _false-ly_),它将跳过检查下一个参数,因为整个参数已经是false
。 - Gideon&
而不是&&
不会强制操作数的左侧先进行求值:在两个操作数之间,使用&
时不存在序列点。使用&
时,右侧可能会先进行求值。OP 在询问&&
是正确的。使用&
会导致未定义行为。请参见答案。 - chux - Reinstate Monica