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

Does "the" C standard specify which standard a compiler has to adhere to?

我刚刚尝试使用 GNU 编译器版本 4.9.2 编译 C 程序。源代码包含一些 for int i=0; ... 语句,编译器给了我一个错误,并指示我应该使用 -std=c99 来编译 for 循环初始声明 。显然,这样的声明在 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 标准并说你 René Nyffenegger 必须遵守 2018 C 标准。他们不是立法机构。私人之间有合同说一些项目将按照这个标准或那个标准生产,但那些是私人协议,而不是 public 法律。

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

For an explanation of the voluntary nature of standards, the meaning of ISO specific terms and expressions related to conformity assessment, as well as information about ISO’s adherence to the World Trade Organization (WTO) principles in the Technical Barriers to Trade (TBT), see the following URL: 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" 的完全符合规范的实现所需的代码量可能超过总代码 space 可用)。此外,不能保证每个符合标准的实现都适用于任何特定目的(实际上,有可能设计出不适合任何目的的 C 实现,除非证明 C 标准不强制有用) .

大多数高质量的 C 开发系统都可以在不同模式下调用,这些模式可能符合(或不符合)不同版本的标准,并且可能适合(或不适合)各种用途。从标准的角度来看,可以调用开发系统的每种不同模式都将是不同的实现。我认为让标准根据对流行特性的支持(或不支持)对实现进行子分类是很有用的,或者保证它们适合(或不适合)常见目的(例如低级或系统编程)但标准还没有这样做。