"the" C 标准是否指定编译器必须遵守哪个标准?



我刚刚尝试用GNU编译器4.9.2版本编译一个C程序。源代码包含一些for int i=0; ...语句,编译器给了我一个错误,并指示我应该使用-std=c99来编译循环初始声明的。显然,这种声明在C99之前是无效的。

在另一台机器上,我有一个更新的GNU编译器(8.1.1),在那里我可以编译相同的源代码,而无需显式指定-std=c99

因为GNU显然使他们的编译器C99在4.9.2和8.1.1之间兼容,这让我想到了一个问题,即最近的C标准是否规定编译器必须遵守C99(或其他标准)。

选择是否遵守C标准或其特定版本是自愿的。选择不是来自C标准。它来自外面。任何一个实现C的人都会决定是否符合2018年的C标准(或者大部分但不完全符合),是否符合2011年C标准,是否符合C的一些"K&R"概念,或者其他什么。C标准中没有任何内容表明,如果你符合这个标准,你的编译器必须符合以前的版本。在选择以符合标准之前,标准实际上不能要求您执行任何操作。

C标准和制定它的人以及支持和发布它的标准组织几乎没有权力让任何人做任何事情。他们不能发布C标准,并说你,勒内·尼芬格,必须遵守2018年的C标准。他们不是立法机构。私营部门之间的合同规定,一些项目将按照这个标准或那个标准生产,但这些都是私人协议,而不是公法。

在2018年C标准中,前言第8段说:

有关标准的自愿性、与合格评定相关的ISO特定术语和表达的含义,以及ISO在技术性贸易壁垒(TBT)中遵守世界贸易组织(WTO)原则的信息,请参阅以下网址:http://www.ISO.org/ISO/foreword.html。

标准组织也不能禁止您编写符合或不符合任何特定版本标准的C编译器,也不能禁止编写基本但不完全符合的编译器。

如果你在商业上使用C标准的名称,也许是通过声称符合它,标准组织可能在这方面拥有一些法律权利。这涉及国际法和许多管辖区的法律,我不能权威地谈论这些法律。我没有听说有人声称符合C标准会出现任何问题。

当新版本发布时,标准组织会正式撤回旧版本的标准。这不会阻止您编写符合旧版本的C实现,但会阻止您在不符合当前版本的情况下声称自己符合当前版本。(例如,如果你同意的合同要求你遵守当前的C标准,那么当组织发布新版本并撤回旧版本时,情况就会改变。)

在GCC 5.0之前,它(最紧密地)遵循的默认标准是C90标准——不指定标准等同于指定-std=gnu90

从5.0开始,默认值更改为C11标准,因此不指定标准等同于指定-std=gnu11

您的两个编译器版本显示了这种行为。

请注意,C标准只规定了编译器必须做些什么才能遵守该标准。它没有规定编译器对以前或将来版本的标准的行为;就标准而言,该标准只有一个版本。编译器实现对其他版本的处理完全取决于编译器编写器。

当然,您可以用显式版本覆盖GCC的默认行为:

  • -ansi
  • -std=c90
  • -std=c99
  • -std=c11
  • -std=gnu90
  • -std=gnu99
  • -std=gnu11
  • …和其他一些变体

-ansi选项等效于-std=c90-std=cXX-std=gnuXX之间的区别在于,c版本没有为各种扩展设置宏,因此您可能必须明确表示要使用POSIX接口,例如,使用-D_XOPEN_SOURCE=700等选项,而gnu版本会自动设置这些宏。

C标准的每个版本都将实现分为两类:符合该标准特定版本的实现和不符合该标准的实现。没有任何C语言警察会打断任何销售不合规实施方案的人的膝盖骨。事实上,在某些情况下,不合格的实现比任何合格的实现都更有用(例如,在一些小型嵌入式平台上,生成"printf"的完全合格实现所需的代码量可能超过可用的总代码空间)。此外,不能保证每一个符合要求的实施都适用于任何特定目的(事实上,除了证明C标准不要求有用之外,还可以设计一个不适用于任何目的的C实施)。

大多数质量C开发系统可以以不同的模式调用,这些模式可能符合(或不符合)不同版本的标准,并且可能适合(或不适合)用于各种目的。从标准的角度来看,可以调用开发系统的每一种不同模式都是不同的实现方式。我认为,让标准根据其对流行功能的支持(或缺乏支持)或保证对实现进行分类是有用的,这些功能或保证将使它们适合(或不适合)用于通用目的(例如低级或系统编程),但到目前为止,标准还没有这样做

最新更新