【问题标题】:Explain working of this C program解释这个 C 程序的工作原理
【发布时间】:2011-07-14 18:12:54
【问题描述】:

请解释每种情况下的工作。

为什么两种情况的输出相同?

案例一:

int main (void)
{
    int i = 5;
    if(i == ++i)           //plz explain here How values are checked
       printf("Equal");
    else
      printf("Not Equal");

  return 0;
}
//Output: Equal;

案例二:

int main (void)
{
    int i = 5;
    if(++i == i)            //plz explain here How values are checked
       printf("Equal");
    else
      printf("Not Equal");

  return 0;
}
//Output: Equal;

【问题讨论】:

    标签: c operators


    【解决方案1】:

    这些程序都无效;如果没有序列点,则不允许读取和更新相同的变量。因此,这些程序中的任何一个将做什么都是未定义的行为,因此它们可能碰巧在您的编译器和机器上返回相同的答案这一事实并不意味着什么。

    【讨论】:

    • @Javed Akram:是的——未定义行为的一个可能结果是代码似乎可以正常工作,甚至可能产生您期望的结果。再说一次,它可能不会做任何一个。当然,最常见的结果是它似乎在测试中运行良好,然后在您为客户演示时却做了一些可怕的事情。
    • @Jerry 好吧,我不认为机器代码会因为演示而波动,但是尝试切换编译器(即使是简单的升级也可以解决问题),看看你什么时候会开始哭泣。跨度>
    • @Jerry @Jeremiah,所以请解释一下这两个程序中未定义的行为在哪里
    • @stefan:机器代码本身可能不会改变,但是它运行的环境可以并且将会改变到足以导致问题。
    • @Javed Akram: C99, §6.5/2: “在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的评估修改一次。此外,先前的值应只读以确定要存储的值。”旧的 C 标准有类似的要求,尽管它的段落编号不同。
    【解决方案2】:

    它是相等的,因为这是 C。正如另一个答案所说,此操作的结果是未定义的,因为您违反了 C 规则——这意味着您在切换编译器时不能保证相同的答案(尽管所有编译器都可能实现类似,这不能保证)。 C 允许您向自己的脚开枪这一事实并不意味着这样做是一种好习惯。

    现在,为什么它会起作用?

    猜想#1:

    i 可以存储在一个寄存器中,比如r1,编译器可能会将整个比较编译成一条具有自动增量寻址模式的 CMP 指令。假设它是CMP ++r1, r1CMP r1, ++r1,那么根据实际的CPU,两者都可能返回一个真正的比较。

    猜想#2:

    编译器可能会将比较编译为:

    inc r1   // increment r1
    CMP r1, r1   // compare with itself
    

    猜想#3:

    编译器可能正在优化以始终将简单的变量访问放在右侧。允许这样做是因为 == 运算符中的执行顺序是未定义的,编译器可以根据需要重新排列。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-28
      • 1970-01-01
      • 2019-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-15
      相关资源
      最近更新 更多