为什么在if语句中未定义的行为是正确的?

时间:2014-01-25 13:43:11

标签: c undefined-behavior

#include <stdio.h>

int main()
{
    int y = 1;
    if (y & (y = 2))
        printf("true \n");

    else
        printf("false \n");
        return 0;
}

输出:

true

在此程序中存在未定义的行为。输出始终为true。我试过几个编译器。任何人都可以解释为什么它一直是true吗?

3 个答案:

答案 0 :(得分:4)

因为观察行为不是定义的行为。您正在使用的编译器(仅通过观察)执行以下操作:

  1. 分配y = 2
  2. 步骤(1)的评估结果
  3. 评估y
  4. 按位 - 和上面步骤(2)和(3)的结果。
  5. 步骤(4)的评估结果
  6. 结果为(2 & 2) true 。问题是,1-2的顺序,然后3不是标准定义的。它可以很容易就是这样:

    1. 评估y
    2. 分配y = 2
    3. 步骤(2)的评估结果
    4. 按位 - 和上面步骤(1)和(3)的结果。
    5. 步骤(4)的评估结果
    6. 结果为(1 & 2) false

      或者它可能完全不同。不是所有编译器都会做第一个,你不能假设因为使用的编译器做了,他们所有都会。你也不能假设因为他们这样做而且你观察到了这种行为,因此它被定义了;事实并非如此。 编译器没有定义行为;标准确实如此,编制者有义务遵守。

      注意:在这个定义时代存在一个漏洞,但它不是不是标准,甚至它也是由标准松散定义的。你会发现标准中的区域是“实现定义的”。在这种情况下,该标准明确指出了这些分歧区域。在这种情况下,您应该咨询您的实现,以获得关于期望行为的明确结论,并且这样做准备好接受这样的事实:这种行为只能在实现的范围内依赖。这(你的样本)这样的漏洞例外。

      我的clang 3.5 rig 似乎(通过我的观察)来运行第二个序列,而不是第一个序列,我可以走你的路,并假设我尝试的所有编译器(其中一个) )表现得像那样,因此它被定义为如此。我会错误地这样做,就像你的假设一样。

      未定义的行为就是这样; 未定义

答案 1 :(得分:0)

您尝试在序列点之间多次修改y的值。如何处理该行为没有标准的方法。所以:

i = i++; // gives undefined behavior also

瓦尔特

答案 2 :(得分:-2)

是的,代码将始终返回True因为任何条件语句中的任何非零值都是True(上面的C-99)或1(C-99)

if (y & (y = 2))
    printf("true %d\n");

在if条件2中,首先分配给y,然后按2分别按2分配。 即0010&amp;因此,它将返回0010。

所以现在你有:

if(2)  //Any non-zero value is true
    printf("true %d\n");