【问题标题】:Need explanation for the output [duplicate]需要解释输出[重复]
【发布时间】:2012-06-29 18:21:40
【问题描述】:

可能重复:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)

#include<stdio.h>
void main()
{
int a=5;
printf("%d\t%d\t%d\n",a,a++,++a);
}

上述程序的输出在 gcc 版本 4.4.3 (Ubuntu 4.4.3-4ubuntu5) 中显示 7 6 7。为什么它显示而不是 7 6 6 ?

【问题讨论】:

  • 程序的行为未定义,因为main()的返回类型必须是int
  • @JamesMcNellis:这不是唯一未定义的行为。
  • 见 [Undefined Behavior and Sequence Points][1] [1]: stackoverflow.com/questions/4176328/…
  • @JonathanLeffler:我知道,但是对于这个问题,我也知道至少有六个人会回答它或提供其他类似问题的链接:-)
  • @JonathanLeffler:这不是 UB。 Moderns 编译器默认将void main() 转换为int main()。此外,main 函数的返回值不会影响程序本身的执行。

标签: c gcc undefined-behavior


【解决方案1】:

您的程序可以显示任何它喜欢的内容并且输出正确。

行为未定义;任何事情都可以发生。

什么是未定义的?

  • 将参数列表中的a 增加两次到printf()

void main() 的行为充其量是实现定义的。 main() 的返回类型应该是int


ISO/IEC 9899:2011 (C 2011) 标准

§ 6.5 表达式

¶2 如果标量对象的副作用相对于不同的副作用是无序的 在同一标量对象或使用同一标量的值的值计算上 对象,行为未定义。如果有多个允许的排序 表达式的子表达式,如果这样一个未排序的一面,则行为未定义 效果发生在任何顺序中。84)

84) 本段呈现未定义的语句表达式如

    i = ++i + 1;
    a[i++] = i;

同时允许

    i = i + 1;
    a[i] = i;

【讨论】:

  • 我不明白,为什么当我测试这个程序时,从主程序返回一个 int 值,并且我得到了一个好的参数:7 6 7?
  • 你可以得到'粉红色的大象'作为打印信息,它仍然有效(虽然相当难以置信)。语言中无法保证将产生什么。评估参数时没有序列点;参数列表中的逗号不是逗号运算符。当所有参数都被评估并且在调用函数之前存在一个序列点;在函数返回之前/之后还有另一个序列点。但是,在评估参数时,一切正常。改变优化可能会改变结果;也可以。
  • 运算符优先级在输出前增量和后增量中是否起任何作用?
  • @javad_shareef:没有;当在一对序列点之间的同一个变量上多次使用前置或后置运算符时,运算符优先级对结果没有影响。
  • @JonathanLeffler:我将 void 更改为 int 并编译了相同的程序。但它显示出相同的输出。我用 Turbo C 编译器尝试了相同的程序,但它显示了一些其他输出。
【解决方案2】:

在 C 中 undefined 的一个语句中多次修改同一个变量。你应该避免这样做,因为结果是不可预测的,并且可能在编译器之间变化。

【讨论】:

  • 它在 Turbo C 编译器中显示了一些其他输出。
  • 它可以显示任何输出,或输出,或着火。语言标准明确说它没有定义行为。任何事情都有可能发生。
【解决方案3】:

“a++”和“++a”的区别简单解释如下:

使用“a++”,增量不在操作之后,而“++a”在操作之前完成。

例如:

a = 0; print("%d ", a++); printf("%d ",a); 会给你0 1

a = 0; print("%d ", ++a); printf("%d ",a); 会给你1 1

【讨论】:

  • 并没有真正回答这个问题。不是前置增量和后置增量的区别
  • 这不是此行为的原因。这是因为 C 标准没有定义评估顺序;表达式可以从右到左或从左到右进行计算;这是导致不同 C 编译器结果不同的原因。编译器编写者可以随意处理它。我在 cmets 上指出的链接对此有很好的解释。
猜你喜欢
  • 2012-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多