本文的思想是介绍C标准。
当C程序在两个不同的编译器中产生不同的结果时该怎么办?
例如,考虑以下简单的C程序。
C
void main() { }
C
#include
int main()
{
int i = 1;
printf("%d %d %d\n", ++i, i++, i);
return 0;
}
上面的程序在gcc中失败,因为main的返回类型为void,但是在Turbo C中编译。我们如何确定它是否是合法的C程序?
考虑下面的程序作为另一个示例。在不同的编译器中产生不同的结果。
C
#include
int main()
{
int i = 1;
printf("%d %d %d\n", ++i, i++, i);
return 0;
}
2 1 3 - using g++ 4.2.1 on Linux.i686
1 2 3 - using SunStudio C++ 5.9 on Linux.i686
2 1 3 - using g++ 4.2.1 on SunOS.x86pc
1 2 3 - using SunStudio C++ 5.9 on SunOS.x86pc
1 2 3 - using g++ 4.2.1 on SunOS.sun4u
1 2 3 - using SunStudio C++ 5.9 on SunOS.sun4u
资料来源:Stackoverflow
哪个编译器是正确的?
所有这些问题的答案都是C标准。在所有这些情况下,我们需要查看C标准对此类程序的说明。
什么是C标准?
最新的C标准是ISO / IEC 9899:2011,也称为C11,其最终草案于2011年发布。在C11之前,存在C99。 C11最终草案可在此处获得。有关C标准的完整历史记录,请参见此内容。
我们可以从C标准知道所有程序的行为吗?
C标准将许多C构造的某些行为设为未定义,而某些则未指定,以简化规范并在实现中提供一定的灵活性。例如,在C语言中,在初始化前使用任何自动变量都会产生不确定的行为,并且未指定子表达式的求值顺序。如果提交了这样的程序,这将特别地使编译器自由地执行最简单或最有效的操作。
那么,以上两个例子的结论是什么?
让我们考虑第一个示例“ void main(){}”,标准接着说到main()的原型。
The function called at program startup is named main. The implementation
declares no prototype for this function. It shall be defined with a return
type of int and with no parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any names
may be used, as they are local to the function in which they are declared):
int main(int argc, char *argv[]) { /* ... */ }
or equivalent;10) or in some other implementation-defined manner.
因此,返回类型void不符合标准,并且某些编译器允许这样做。
让我们谈谈第二个例子。请注意,C语言中的以下语句在未指定的行为下列出。
The order in which the function designator, arguments, and
subexpressions within the arguments are evaluated in a function
call (6.5.2.2).
想要从精选的最佳视频中学习和练习问题,请查看《基础知识到高级C的C基础课程》。