本文的想法是介绍C标准。

C编程语言标准-IDC帮帮忙

当C程序在两个不同的编译器中产生不同的结果时该怎么办?
例如,考虑以下简单的C程序。

void main() { }
在IDE上运行
上面的程序在gcc中失败,因为main的返回类型是void,但它在Turbo C中编译。我们如何判断它是否是合法的C程序?

将以下程序视为另一个示例。它在不同的编译器中产生不同的结果。

#include<stdio.h>
int main()
{
int i = 1;
printf("%d %d %d\n", i++, i++, i);
return 0;
}
在IDE上运行
2 1 3 - 在Linux.i686上使用g ++ 4.2.1
1 2 3 - 在Linux.i686上使用SunStudio C ++ 5.9
2 1 3 - 在SunOS.x86pc上使用g ++ 4.2.1
1 2 3 - 在SunOS.x86pc上使用SunStudio C ++ 5.9
1 2 3 - 在SunOS.sun4u上使用g ++ 4.2.1
1 2 3 - 在SunOS.sun4u上使用SunStudio C ++ 5.9
来源:Stackoverflow

哪个编译器是对的?

所有这些问题的答案都是C标准。在所有这些情况下,我们需要了解C标准对此类程序的评价。

什么是C标准?
最新的C标准是ISO / IEC 9899:2011,也称为C11,最终草案于2011年发布。在C11之前,有C99。C11最终草案可在此处获得。见这对于C类标准完整的历史。

我们能否知道C标准中所有程序的行为?
C标准将许多C构造的某些行为保留为未定义,而某些行为未指定以简化规范并允许在实现中具有一定的灵活性。例如,在C中,在初始化之前使用任何自动变量会产生未定义的行为,并且未指定子表达式的评估顺序。如果提交此类程序,这可以使编译器自由地执行最简单或最有效的操作。

那么上面两个例子的结论是什么?
让我们考虑第一个例子是“void main(){}”,标准说下面是关于main()的原型。

程序启动时调用的函数名为main。实施
声明此函数没有原型。它应定义一个回报
int的类型,没有参数:
int main(void){/ * ... * /}
或者有两个参数(这里称为argc和argv,尽管有任何名称)
可以使用,因为它们是声明它们的函数的本地):
int main(int argc,char * argv []){/ * ... * /}
等效的; 10)或其他一些实现定义的方式。
因此返回类型void不符合标准,它是某些编译器允许的。

我们来谈谈第二个例子。请注意,C标准中的以下语句列在未指定的行为下。

函数指示符,参数和的顺序
参数中的子表达式在函数中计算
如何处理标准中未定义或未指定行为的程序?
作为程序员,使用行为未定义或未指定的编程结构永远不是一个好主意,应始终不鼓励这样的程序。这些程序的输出可能随编译器和/或机器而改变。