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

Tah*_*kar 44 c if-statement logical-operators

{
    int i = 1;
    if (i++ && (i == 1))
        printf("Yes\n");
    else
        printf("No\n");
}
Run Code Online (Sandbox Code Playgroud)

根据我的理解,在if条件中,首先i==1将对应该返回的expression()进行求值1,然后在逻辑上对其进行求1i,因此表达式应该返回1 && 1 == 1,但是else部分被执行.

有人可以解释else部分执行的原因吗?

Jon*_*ler 92

在C中,在操作员的LHS 评估和RHS评估之间存在一个序列点&&,必须在RHS评估之前完成增量并完成.因此,执行i++(等效于i++ != 0)并完成增量(并且表达式的计算结果为true),因此在评估RHS时,i == 2因此整体表达式为false,并且打印出"否".如果&&操作员的LHS 评估为假(0),则由于&&操作员的"短路"特性,不会评估RHS .

只有少数运算符具有在LHS和RHS的评估之间具有序列点的属性:&&,||,(作为运算符,而不是参数列表中的分隔符) - 并且也有? :,这不是二元运算符但是在评估条件之后并且在评估之后的表达式?或之后的表达式:(其中一个或另一个,但不是两个,总是被评估)之前具有序列点.

&&||运营商是唯一的运营商与"短路"属性.&&仅在LHS评估为真时评估RHS :||仅在LHS评估为假时评估RHS .


关于序列点的澄清

Iwillnotexist Idonotexist正确断言:

C11标准没有取消序列点,只有C++ 11标准.

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

1.9程序执行

13 之前排序的是由单个线程(1.10)执行的评估之间的不对称,传递,成对关系,这导致这些评估之间的部分顺序.给定任何两个评估AB,如果 AB之前被排序,那么A的执行应该在B的执行之前.如果是不是之前测序 没有之前测序,然后未测序.[ 注意:未经测试的评估的执行可能会重叠.- 注完 ]评价不定测序当任一个 之前测序之前进行测序,但它是未指定的哪个.[ 注意:不确定顺序的评估不能重叠,但可以先执行.- 结束说明 ]

术语"序列点"根本不出现在C++ 11中(唯一的近似匹配是'序列指针').

C11(ISO/IEC 9899:2011)说:

5.1.2.3程序执行

3 之前排序的是由单个线程执行的评估之间的不对称,传递,成对关系,这导致这些评估之间的部分顺序.给定任何两个评估AB,如果AB之前被排序,那么A 的执行应该在B的执行之前.(相反地,如果是之前测序,然后后测序 如果)不之前或之后测序,然后未测序.当AB之前或之后进行测序时,评估AB不确定的,但是未指定哪一个.13) A的存在序列点 表达式的计算之间意味着具有相关联的每一个值的计算和副作用与其相关联的每一个值的计算和副作用之前测序.(序列点的摘要见附件C.)

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

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

  • 完善.`if((i == 1)&& i ++)`会打印'是'. (9认同)
  • @ Equality7-2521:'在'之前测序','在'之后测序','不确定测序'和'未测序'的术语也适用于C11.我相信新的术语部分是因为在两个标准中增加了线程支持. (3认同)

Sru*_*Suk 40

在这里,一个简单的解释

在此输入图像描述

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

  • @shekharsuman不,我自己发现这个答案最清楚,除非你想以正式方式强调这个概念. (17认同)
  • 干净简单,但它没有解释为什么括号中的表达式没有先执行. (9认同)
  • 这表明发生了什么,但没有解释原因.例如,代码`if(i ++&(i == 1))[...]`(注意单个&符号)会有不同的结果,但你的答案没有提到任何有助于某人解决原因的概念. (5认同)
  • 实际上,我认为这很简单.它通过图解释了行为.这对我来说完全没问题. (3认同)

小智 28

&&在表达式中被使用,它的参数保证是从左到右进行评价.那么i将评估2when (i==1)的值.因此,表达式为false,else将执行该部分.

但是,请注意完整性,如果左参数的计算结果为false或0,则根本不计算右参数.