严格的 C90 代码的 GCC 选项?

Posted

技术标签:

【中文标题】严格的 C90 代码的 GCC 选项?【英文标题】:GCC options for strict C90 code? 【发布时间】:2014-12-17 14:22:54 【问题描述】:

我试图找出在测试 strict C90 一致性时要使用的 gcc 标志组合是什么。根据之前的帖子:GCC options for strictest C code?,我应该只需要一个--std=c90。

但这是我尝试过的:

$ cat t.c
#include <stdint.h> /* added in C99 */

int main()

  uint64_t t;
  return 0;

$ gcc -std=c90 -ansi -pedantic   t.c

上述方法运行良好(没有产生警告/错误)。

有谁知道:

    gcc 标志具有严格的 ISO/IEC 9899:1990 一致性 具有不同标志集的不同编译器(tcc、clang...)?

编辑:

对不起我的措辞,是的,我真的很想模仿一个严格符合 C90 的编译器,换句话说,如果代码尝试使用以后添加的任何功能(想到 C99),它应该会失败。所以pthread 包含头文件应该 在以GNU/GCC calls C90 mode 编译时发出警告(就像 stdint.h 头文件应该在没有 C99 的情况下产生警告)。 -pedantic 很好地警告我long long 的使用,我不明白为什么它不应该警告我uint64_t

我使用了 ISO/IEC 9899:1990 的术语,引用自:

http://en.wikipedia.org/wiki/C_(programming_language)#ANSI_C_and_ISO_C

1990 年,ANSI C 标准(带有格式更改)被 国际标准化组织 (ISO) 作为 ISO/IEC 9899:1990,有时也称为 C90。因此,术语“C89” 和“C90”指的是同一种编程语言。

EDIT2:

GCC 文档其实很清楚:

C99 标准中的某些功能被接受为 C90 模式下的扩展,以及 C11 中的一些功能 标准被接受为 C90 和 C99 模式中的扩展。

所以我的问题被改写为:

在 Linux 系统上是否有编译器 + 标准包含头文件,严格符合 C90?

【问题讨论】:

请注意,C90 是在 ISO/IEC 9899 标准中指定的。您要求 ISO/IEC 9945-1 是 POSIX 标准。 我还没有听说过允许你检查这个的编译器。一些编译器,例如 gcc 和 clang 以及 3.party 标准库,在相当长的时间内支持所请求的标准,特别是在语言级别,但它们并不意味着是合规检查器。对于库功能,它甚至更没有实际意义,因为 C 允许非标准库/头文件可用,没有什么能阻止实现在 c89 编译器中提供 stdint.h - 例如gcc 和 clang 不提供库/头文件 - 留给 3. 方(通常是 linux 上的 glibc) 你说应该发出警告,你的证据呢?梳理标准后,我看不到任何地方说需要编译器来发出诊断。 @malat &lt;stdint.h&gt; 中没有任何内容应该无法在 C90 模式下编译。允许实现为它不提供的相应类型省略任何类型定义/宏。如果您尝试在 C++03 中包含 C++11 标头,编译器本身不会发出诊断信息,而是 GCC 在标头文件中有 #error pragma。 我猜维护标头的人可以通过添加#if (__STDC_VERSION__ &lt; 199901 &amp;&amp; __PEDANTIC__) 之类的内容,然后向例如#error 指令添加类似的东西来轻松实现这一点。 stdint.h。然而,他们是否会这样做是值得怀疑的,因为我认为绝大多数用户并不真正需要该功能,而且他们可能不会为“以防万一”修补两打标题。当然,您可以随时尝试提交补丁。 【参考方案1】:

C90 合规性并不意味着编译器不能提供 C90 标准中未提及的 other 标头。 (例如,sys/socket.h。)如果您出于某种奇怪的原因想要禁止这些,您可以通过 -I 选项来添加额外的包含路径,并在该路径中放置所有 C99 标头的版本,这些标头是只需#error Don't include me

【讨论】:

“出于某种奇怪的原因”——原因一点也不奇怪。如果 OP 想要测试他们的代码以确保它没有任何 C99 或 OS 特定的依赖项,那么他们绝对确实希望限制自己使用这些标头。 编译器也可以解析给定的标头,解析宏(如果有),并且不包含任何内容,因为在扩展宏并评估条件后,标头不会生成任何文本/code 作为传递给编译器的选项的结果而包含在内。毕竟,使用#ifdefifndef 或其他选项来保护您的标头免受不必要的包含并不难。 @TheParamagneticCroissant 我不知道有任何专门用于禁止 C99 构造的编译器/运行时。那将是一个完全没有回报的编译器来维护。即使在 GCC 提供的 C90 头文件中,我也可以肯定有些函数定义不是 C90 标准的一部分。【参考方案2】:

请记住,GCC 本身是符合指定的 C 标准的独立实现;这样的实现只提供了标准头文件的一小部分,实际上不提供 C 标准库的实际功能,而是依赖另一方——例如 Linux 系统上的glibc——来提供 C 标准库的功能。

您所寻求的不仅是在您使用 C90 中没有的 C99/C11/GNU 语言 功能时发出警告,而且在您使用 时发出警告> C90 本身未定义的功能。可悲的是,由于上述原因,单独的编译器无法做到这一点——它与libc 的使用方式无关。在glibc 系统上,C 标准库将选择-std=c90-ansi 定义的宏:

使用-ansi 选项时预定义宏__STRICT_ANSI__。一些头文件可能会注意到这个宏,并避免声明某些函数或定义 ISO 标准不要求的某些宏;这是为了避免干扰任何可能将这些名称用于其他用途的程序。

并通过关闭免费扩展为您提供一些帮助:

如果您使用‘gcc -ansi’ 编译程序,则只能获得 ISO C 库功能,除非您通过定义一个或多个功能宏来明确请求其他功能。

但是,这仅涵盖扩展和 POSIX-but-not-ISO C 函数;如果在 ISO C 和 POSIX.1 中以不同方式指定函数的行为,它不会拯救您!

【讨论】:

以上是关于严格的 C90 代码的 GCC 选项?的主要内容,如果未能解决你的问题,请参考以下文章

推荐的 Clang 命令行选项

gcc编译选项pedantic(GCC编译器的C++标准严格模式)

GCC警告选项例解

GCC 编译选项

gcc 编译控制选项

是否可以从 gcc 的源代码中确定或设置编译器选项?