【问题标题】:How to disable GNU C extensions?如何禁用 GNU C 扩展?
【发布时间】:2016-08-14 07:10:56
【问题描述】:

正如您在下面的代码中看到的,我在main() 中引入了一个嵌套函数:

#include <stdio.h>

int main(){
 int a=5;
 printf("%d\n",a);
 {
  int a=10;
  printf("%d\n",a);
 }
 printf("%d\n",a);

 //Nested function
 int main(int a){
 if(a>0)printf("%d\n",a--);
 return 0;
 }

 main(7);
 return 0;
}

据我所知,我在 gcc 中使用了 -std=c99 标志来“禁用”不必要的扩展,但没有收到任何错误。

gcc temp3.c -std=c99 -o temp3.out

我哪里做错了?

【问题讨论】:

  • 添加 -pedantic -Werror 应该可以解决这个问题。
  • 那-std=c99标志有什么用呢?
  • -std=c99 标志禁用 GCC 认为应该禁用的 GNU 扩展——例如 POSIX 版本等。C Dialect Options 的含义见-std=-pedantic 的含义见Warning Options

标签: c gcc


【解决方案1】:
  • -pedantic-Werror 添加到命令行。

在 Mac OS X 10.11.6 上使用 GCC 6.1.0,将您的原始代码放在文件 ped73.c 和我的默认编译选项中,我得到:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
>     -Wold-style-definition ped73.c -o ped73 
ped73.c:3:5: error: function declaration isn’t a prototype [-Werror=strict-prototypes]
 int main(){
     ^~~~
ped73.c: In function ‘main’:
ped73.c:3:5: error: old-style function definition [-Werror=old-style-definition]
ped73.c:13:6: error: ‘main’ takes only zero or two arguments [-Werror=main]
  int main(int a){
      ^~~~
ped73.c:13:6: error: ‘main’ is normally a non-static function [-Werror=main]
$

将嵌套函数重命名为nested 并使用int main(void),我得到:

$ gcc -O3 -g-std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes 
>     -Wold-style-definition -o ped73
$

使用额外选项-pedantic 我得到:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
>     -Wold-style-definition -pedantic ped73.c -o ped73 
ped73.c: In function ‘main’:
ped73.c:13:2: error: ISO C forbids nested functions [-Werror=pedantic]
  int nested(int a){
  ^~~
cc1: all warnings being treated as errors
$

那么-std=c99的意义何在?

-std=c99 标志禁用 GCC 认为应该禁用的 GNU 扩展——例如 POSIX 版本等。有关-std= 的含义,请参见C Dialect Options-pedantic的含义见Warning Options

-Wpedantic
-pedantic

发出严格的 ISO C 和 ISO C++ 要求的所有警告;拒绝所有使用禁止扩展的程序,以及其他一些不遵循 ISO C 和 ISO C++ 的程序。对于 ISO C,遵循使用的任何 -std 选项指定的 ISO C 标准版本。

有效的 ISO C 和 ISO C++ 程序应该在有或没有这个选项的情况下正确编译(尽管很少有需要 -ansi-std 选项来指定所需的 ISO C 版本)。但是,如果没有此选项,某些 GNU 扩展以及传统的 C 和 C++ 功能也将受支持。使用此选项,它们会被拒绝。

-Wpedantic 不会在使用名称以 __ 开头和结尾的备用关键字时产生警告消息。在__extension__ 后面的表达式中也禁用了迂腐警告。但是,只有系统头文件应该使用这些转义路径;应用程序应避免使用它们。请参阅备用关键字。

一些用户尝试使用 -Wpedantic 来检查程序是否严格遵守 ISO C。他们很快发现它并没有完全按照他们的意愿行事:它发现了一些非 ISO 实践,但不是全部——只有那些 ISO C 需要诊断的实践,以及一些已经添加了诊断的其他实践。

报告任何不符合 ISO C 的功能在某些情况下可能很有用,但需要大量额外的工作,并且与 -Wpedantic 完全不同。我们没有计划在不久的将来支持这样的功能。

如果用 -std 指定的标准表示 C 的 GNU 扩展方言,例如“gnu90”或“gnu99”,则有相应的基本标准,即 GNU 扩展方言所基于的 ISO C 版本。来自 -Wpedantic 的警告在基本标准要求的地方给出。 (仅针对不在指定 GNU C 方言中的功能发出此类警告是没有意义的,因为根据定义,C 的 GNU 方言包括编译器通过给定选项支持的所有功能,并且没有什么需要警告的.)

还有一个不同的选项会产生迂腐错误:

-pedantic-errors

当基本标准(参见-Wpedantic)需要诊断时给出错误,在某些情况下,在编译时存在未定义的行为,而在其他一些情况下,不会阻止编译根据标准。这不等同于-Werror=pedantic,因为存在由该选项启用而后者未启用的错误,反之亦然。


关于使用哪些 GCC 编译器选项存在多个问题,包括:

毫无疑问,还有许多其他可以添加到该列表中。基本上,我使用的默认选项确保函数在使用之前被声明(或者,在使用之前被定义为static函数),并且函数声明具有完整的原型——没有空括号()——和使用 -Wall-Wextra 发现许多其他常规问题,包括格式字符串和 printf()scanf() 系列函数的参数之间的不匹配。

【讨论】:

  • 这是我在将-pedantic 添加到默认编译字符串时偶然发现的。我发现它记录的唯一地方是Language Standards Supported by GCC
  • 可能想强调并解释您对-Wall -Wextra 的用法。这些导致编译器报告默认情况下未配置的各种问题。并非所有这些都与避免 gcc 扩展有关,但它们可能表明存在错误(可疑转换等),或者与其他编译器无法按预期工作。如果-Werror 不会导致警告终止,那么“不接受触发警告的代码”的故意策略将会。
  • 这仍然不会禁用 gnu 扩展,除了那些与语法相关的扩展。例如。通过联合的类型双关仍然有效,即使在这种模式下也被允许
  • 我不明白这是如何回答这个问题的。将所有警告变成错误与禁用 GNU 扩展不同。想象一下我作为一名教师的工作,试图自动化部分练习提交,不想看到使用的 GNU 扩展,但也不想因为其他警告而停止编译。
  • 你不能完全停止 GNU 扩展。没有提供这样做的机制。这是尽可能接近的。
猜你喜欢
  • 2015-05-15
  • 1970-01-01
  • 2010-12-05
  • 2020-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多