如何禁用GNU C扩展?

May*_*rma 7 c gcc

正如您在以下代码中看到的,我在以下代码中引入了嵌套函数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;
}
Run Code Online (Sandbox Code Playgroud)

据我所知,我使用-std=c99gcc中的标志来"禁用"不必要的扩展,但我没有得到任何错误.

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

我在哪里弄错了?

Jon*_*ler 12

  • 添加-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]
$
Run Code Online (Sandbox Code Playgroud)

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

$ gcc -O3 -g-std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes 
>     -Wold-style-definition -o ped73
$
Run Code Online (Sandbox Code Playgroud)

使用额外选项-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
$
Run Code Online (Sandbox Code Playgroud)

那有什么意义-std=c99呢?

-std=c99标志禁用GCC认为应该禁用的GNU扩展 - 例如POSIX版本等.有关含义,请参阅C方言选项-std= ; 请参阅警告选项的含义-pedantic.

-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()功能的家庭.

  • 这仍然不会禁用 gnu 扩展,除了那些与语法相关的扩展。例如,通过联合进行类型双关仍然有效,并且即使在这种模式下也是允许的 (2认同)