严格符合 C90 标准的 GCC 选项是什么?

15

我正在尝试找到测试严格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

上述方法有效(没有产生警告/错误)。
有人知道以下内容吗:
1. gcc标志以严格的ISO/IEC 9899:1990一致性 2. 具有不同标志集的其他编译器(tcc、clang等)?
编辑:
对我的措辞很抱歉,是的,我真的想模仿一个严格符合C90标准的编译器,换句话说,如果代码尝试使用后来添加的任何功能(如C99),则应该失败。因此,在GNU/GCC称为C90模式下编译pthread包含头文件应该发出警告(就像stdint.h头文件在没有C99的情况下应该发出警告一样)。-pedantic很好地警告我使用long long,我不明白为什么它不会警告我使用uint64_t
我引用了ISO/IEC 9899:1990的术语。 1990年,ANSI C标准(经过格式更改)被国际标准化组织(ISO)采用为ISO/IEC 9899:1990,有时称为C90。因此,“C89”和“C90”这两个术语指的是同一种编程语言。
编辑2:

GCC文档实际上非常清楚:

在C90模式下,一些属于C99标准的特性被接受为扩展功能,在C90和C99模式下,一些属于C11标准的特性被接受为扩展功能。

所以我的问题可以重新表述为:

  • 在Linux系统上是否有一个编译器+标准包含头文件严格遵守C90?

1
请注意,C90在标准ISO/IEC 9899中指定。您要求的是ISO/IEC 9945-1,这是POSIX标准。 - Lundin
我没有听说过有哪个编译器可以让你检查这个。一些编译器,如gcc和clang,结合第三方标准库在语言层面上尽力支持所需的标准,但它们并不是用来进行合规性检查的。对于库功��来说,更加无意义,因为C语言允许使用非标准库/头文件,因此实现可以提供stdint.h在c89编译器中使用-例如,gcc和clang不提供库/头文件-这留给了第三方(通常是linux上的glibc) - nos
1
你说应该发出一个警告,有证据吗?在查看了标准之后,我没有找到任何地方表明编译器需要发出诊断信息。 - user3920237
2
@malat 在 C90 模式下,<stdint.h> 中没有任何东西应该无法编译。实现允许省略任何它不提供的相应类型的 typedefs/macros。如果您尝试在 C++03 中包含 C++11 标头,则编译器本身不会发出诊断,而是 GCC 在头文件中有一个 #error pragma。 - user3920237
1
我猜维护头文件的人可以通过添加类似于#if (__STDC_VERSION__ < 199901 && __PEDANTIC__)的内容,然后在例如stdint.h中加入一个#error指令来轻松实现。然而,他们可能不会这样做,因为我认为绝大多数用户并不真正需要该功能,而且他们可能不会打补丁修复两打头文件“以防万一”。当然,你总是可以尝试提交一个补丁。 - Damon
显示剩余4条评论
2个回答

14

C90兼容性并不意味着编译器不能提供在C90标准中未提及的其他头文件。 (例如sys/socket.h)。如果您有某些奇怪的原因想禁止它们,可以传递-I选项以添加额外的包含路径,并在该路径中放置所有仅限于C99的头文件版本,这些版本只需使用#error Don't include me即可。


4
“for some strange reason”的意思并不是真的有奇怪的原因。如果OP想要测试他们的代码,以确保它没有任何C99或特定于操作系统的依赖性,那么他们绝对需要限制自己不使用那些头文件。请注意,此处的“they”指的是OP本人。 - The Paramagnetic Croissant
编译器也可以解析给定的头文件,如果有宏定义,则解析它们,但不包含任何内容,因为在扩展宏和评估条件之后,头文件不会生成任何文本/代码作为传递给编译器的选项的结果。毕竟,使用#ifdefifndef或其他选项来保护您的头文件免受不必要的包含并不难。 - user2485710
@TheParamagneticCroissant 我不知道是否存在专门用于禁止C99结构的编译器/运行时。那将是一个完全没有回报的编译器维护工作。即使在GCC提供的C90头文件中,我相信有一些函数定义并不属于C90标准。 - Sneftel

2
请注意,GCC本身是符合C标准规定的自由实现,这样的实现仅提供了一小部分标准头文件,并且实际上没有提供C标准库的实际功能,而是依赖于另一个方案——例如Linux系统上的glibc——来提供C标准库的功能。
您所寻找的是不仅在您使用C99/C11/GNU语言特性时警告您,该特性不在C90中,而且在您使用C90本身未定义的库函数时也会警告您。不幸的是,编译器本身不能做到这一点,因为它对使用的libc无从得知。在glibc系统上,C标准库将捕获由-std=c90或-ansi定义的宏。
当使用-ansi选项时,宏__STRICT_ANSI__是预定义的。一些头文件可能会注意到这个宏,并避免声明某些函数或定义某些宏,因为ISO标准不要求这样做。这是为了避免干扰任何可能将这些名称用于其他事情的程序。
如果您使用‘gcc -ansi’编译程序,则只获得ISO C库功能,除非您通过定义一个或多个特性宏来显式请求其他功能。
然而,这仅涵盖扩展和POSIX但不是ISO C函数;如果一个函数的行为在ISO C和POSIX.1中有不同的规定,那么这种方法就无法解决问题!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接