📜  C编程语言标准

📅  最后修改于: 2021-05-26 01:24:23             🧑  作者: Mango

本文的思想是介绍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基础课程》。