1. 主页
  2. 文档
  3. C语言教程
  4. C语言基础教程
  5. C 编程语言标准

C 编程语言标准

本文的思路是介绍C标准。 

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

void main() { }

上述程序在 gcc 中失败,因为 main 的返回类型为 void,但它在 Turbo C 中编译。我们如何确定它是否是合法的 C 程序? 

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

#include<stdio.h>
int main()
{
int i = 1;
printf("%d %d %d\n", ++i, i++, i);
return 0;
}
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[]) { /* ... */ 

所以返回类型 void 不符合标准,这是某些编译器允许的。

如何处理其行为在标准中未定义或未指定的程序? 
作为程序员,使用行为未定义或未指定的编程结构绝不是一个好主意,应始终不鼓励此类程序。此类程序的输出可能会随编译器和/或机器而变化。

 

 

这篇文章对您有用吗? 1