为什么不同的C编译器可以为C程序提供不同的输出?

时间:2011-08-26 18:33:18

标签: c compiler-construction

我怀疑为什么不同的编译器会向同一个C程序提供不同的输出。如果有一个标准的C,那么为什么这些着名的编译器不会完全使用它。 输出的差异是由16位32位编译器引起的,那么所有那些产生差异的问题是什么。

4 个答案:

答案 0 :(得分:10)

你有一个例子吗?

语言是标准化的,但它的很多方面都是实现定义的,甚至是未定义的。

例如,这个:

printf("sizeof (int) = %u\n", (unsigned)sizeof (int));

将在不同的系统上打印不同的数字,具体取决于int的大小。

答案 1 :(得分:4)

语言标准为实现留下了几个自由度。

首先,即使程序正确实现,其行为也可能取决于实现定义的语言功能。例如,不同的实现可以具有不同的基本整数类型范围。

其次,程序可能会被打破。此上下文中的损坏程序是依赖于语言未定义或未指定的行为的程序。该程序似乎以某种方式“起作用”,但其实际行为将取决于不可预测的因素,因此将不一致。

实践表明,在许多(如果不是大多数)人们抱怨行为不一致的C程序的情况下,他们实际上没有意识到他们正在处理一个破碎的程序。

答案 2 :(得分:2)

C中有许多内容是实现定义的。这意味着创建编译器的人可以选择他们想要处理这些情况的方式。通常,为了便于移植,在大多数情况下最好不依赖于未定义的行为,即使大多数或所有编译器都以相同的方式处理它。如果你提供一些不同编译器处理不同的代码,也许我们可以告诉你他们为什么这样做以及如何修复它。

未定义行为的一个示例是引用未初始化的变量,如下所示:

int *a;
printf("%d", *a);

在大多数实现中,您将看到一些没有任何意义的垃圾整数(以及警告)。它是存储在a所指向的内存位置中的任何值;但是,从技术上讲,实现可能已经指定引用未初始化的变量将始终给出0(或类似的东西)。不是这种情况的原因是因为实施起来要困难得多。尽管如此,你仍然不应该依赖a所指向的内存位置。它可能是也可能不是你得到的。

答案 3 :(得分:0)

在大多数情况下,当程序员使用未定义的行为时,编译器必须尝试猜测你的意思。

另一个潜在问题的例子:C ++ 0x刚刚获得批准,但最终草案尚未公开。一旦可用,一些编译器可能会在其他编译器之前添加支持。

解决方案的一部分:许多编译器都有办法编译到某个规范。例如,使用GCC,您可以使用“gcc programname.c -ansi”进行编译,以确保您的代码符合ANSI标准。这将确保一致性。