为什么" if(i ++&&(i == 1))" false其中i是一个持有值1的int?

时间:2015-07-12 03:26:10

标签: c if-statement logical-operators

{
    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部分被执行了吗?

5 个答案:

答案 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)

这里有一个简单的解释

enter image description here

这就是为什么这种情况会变成'假'

答案 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。