您的位置:首页 > 运维架构 > Linux

GCC警告选项及使用

2013-08-28 15:26 225 查看
不符合ANSI/ISO的源代码

/*

*  pedant.c - use -ansi, -pedantic or -pedantic-errors

*/

#include <stdio.h>

void main(void)

{

  long long int i = 0l;

  printf("This is a non-conforming c program\n");

}

使用gcc pedant.c -o pedant这个命令时,编译器会警告main函数的返回类型无效:

$gcc pedant.c -o pedant

pedant.c:In function 'main':

pedant.c:7 warning:return type of 'main' is not 'int'

现在给gcc加上-ansi选项:

$gcc -ansi pedant.c -o pedant

$gcc pedant.c -o pedant

pedant.c: In function 'main'

pedant.c:7 warning: return type of 'main' is not 'int'

gcc再次给出了同样的警告信息,并忽略了无效的数据类型.

-ansi,-pedantic以及-pedantic-errors编译选项并不能保证被编译的程序的ANSI/ISO兼容性,它们仅被用来帮助程序员离这个目标更近.

$gcc -Wall pedant.c -o pedant

pedant.c:7: warning: return type of 'main' is not 'int'

pedant.c: In function 'main':

pedant.c:8 warning: unused variable 'i'

-Wall系列选项的另一个极端是-w选项,它能关闭所有的警告信息。-W{warning}选项的作用是打开warning所指出的用户感兴趣的特殊警告信息,比如隐身函数说明(-Wimplicit-function-declaration)或者隐身声明返回类型的函数(-Wreturn-type).前者的作用在于它提示出定义了一个函数却没有事先声明或者忘记了包含适当的头文件.后者的作用在于指出声明的函数可能没有指定它的返回类型,此时默认的返回类型为int.

提示:如果只想检查语法而实际上不做如何编译工作,那么可以调用带有-fsyntax-only参数的GCC.

选项                        说明

-Wcomment                   如果出现了注解嵌套(在第一个/*之后又出现了第二个/*)则发出警告

-Wformat                    如果传递给printf及及其相关函数的参数和对应的格式字符串中指定的类型不平配则发出警告

-Wmain                      如果main的返回类型不是int或者调用main时使用的参数数目不正确则不出警告

-Wparentheses               如果在出现了赋值(例如,(n=10))的地方使用了括号,而那里根据前后关系推断应该是比较(例如,(n==100))而非赋值的时候,或者如果括号能够解决运算优先级问题的时候,发出警告

-Wswitch                    如果swtich语句少了它的一个或多个枚举值的case分支(只有索引值是enum类型时才适用)则发出警告

-Wunused                    如果声明的变量没有使用,或者函数声明为static类型但却从未使用,则发出警告

-Wuninitialized             如果使用的自动变量没有初始化则发出警告

-Wundef                     如果在#if宏中使用了未定义的变量作判断则发出警告

-Winline                    如果函数不能被内联则发出警告

-Wmissing-declarations      如果定义了全局函数但却没有在任何头文件中声明它,则发出警告

-Wlong-long                 如果使用了long long类型则发出警告

-Werror                     将所有的警告转变为错误

常见的编程错误:

/*

*  blunder.c - Mistakes caught by -W(warning)

*/

#include <stdio.h>

#include <stdlib.h>

int main(int argc, char *argv[])

{

  int i, j;

  printf("%c\n", "not a character");  /* -Wformat */

  if(i =10)                          /*-Wparenthesses */

    printf("oops\n");

  if(j !=10)                        /* -Wuninitialized */

    printf("another oops\n");

  /* /**/                            /*-Wcomment */

  no_decl();                          /*-Wmissing-declaration */

  return (EXIT_SUCCESS);

}

void no_decl(void)

{

  printf("no_decl\n");

}

$gcc blunder.c -o blunder

blunder.c:27: warning: type mismatch with previous implicit declaration

blunder.c:21: warning: previous implicit declaration of 'no_decl'

blunder.c:27: warning: 'no_decl' was previously implicitly declared to return 'int'

gcc只发出了和隐式声明no_decl函数有关的警告.它忽略了其他潜在的错误,这些错误包括:

.传递给printf的参数类型(一个字符串)和格式化字符串定义的类型(一个字符)不匹配.这会产生一个-Wformat警告.

.变量i和j使用前都没有初始化.它们中的任何一个都产生-Wuninitialized警告.

.在根据前后关系推断应该对变量i的值做比较的地方,却对变量i进行赋值.这应该会产生一个-Wparentheses警告.
.在注释嵌套开始的地方应该会产生一个-Wcomment警告.

文章转自:
http://www.blogjava.net/ivanwan/archive/2005/08/04/9338.html
[介绍] 
gcc and g++分别是gnu的c & c++编译器 gcc/g++在执行编译工作的时候,总共需要4步 

1.预处理,生成.i的文件[预处理器cpp] 
2.将预处理后的文件不转换成汇编语言,生成文件.s[编译器egcs] 
3.有汇编变为目标代码(机器代码)生成.o的文件[汇编器as] 
4.连接目标代码,生成可执行程序[链接器ld] 
[参数详解] 
-x language filename 
  设定文件所使用的语言,使后缀名无效,对以后的多个有效.也就是根据约定C语言的后 
缀名称是.c的,而C++的后缀名是.C或者.cpp,如果你很个性,决定你的C代码文件的后缀 
名是.pig 哈哈,那你就要用这个参数,这个参数对他后面的文件名都起作用,除非到了 
下一个参数的使用。 
  可以使用的参数吗有下面的这些 
  `c', `objective-c', `c-header', `c++', `cpp-output', `assembler', and `a 
ssembler-with-cpp'. 
  看到英文,应该可以理解的。 
  例子用法: 
  gcc -x c hello.pig 
   
-x none filename 
  关掉上一个选项,也就是让gcc根据文件名后缀,自动识别文件类型 
  例子用法: 
  gcc -x c hello.pig -x none hello2.c 
   
-c 
  只激活预处理,编译,和汇编,也就是他只把程序做成obj文件 
  例子用法: 
  gcc -c hello.c 
  他将生成.o的obj文件 
-S 
  只激活预处理和编译,就是指把文件编译成为汇编代码。 
  例子用法 
  gcc -S hello.c 
  他将生成.s的汇编代码,你可以用文本编辑器察看 
-E 
  只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面. 
  例子用法: 
  gcc -E hello.c > pianoapan.txt 
  gcc -E hello.c | more 
  慢慢看吧,一个hello word 也要与处理成800行的代码 
-o 
  制定目标名称,缺省的时候,gcc 编译出来的文件是a.out,很难听,如果你和我有同感 
,改掉它,哈哈 
  例子用法 
  gcc -o hello.exe hello.c (哦,windows用习惯了) 
  gcc -o hello.asm -S hello.c 
-pipe 
  使用管道代替编译中临时文件,在使用非gnu汇编工具的时候,可能有些问题 
  gcc -pipe -o hello.exe hello.c 
-ansi 
  关闭gnu c中与ansi c不兼容的特性,激活ansi c的专有特性(包括禁止一些asm inl 
ine typeof关键字,以及UNIX,vax等预处理宏, 
-fno-asm 
  此选项实现ansi选项的功能的一部分,它禁止将asm,inline和typeof用作关键字。 
     
-fno-strict-prototype 
  只对g++起作用,使用这个选项,g++将对不带参数的函数,都认为是没有显式的对参数 
的个数和类型说明,而不是没有参数. 
  而gcc无论是否使用这个参数,都将对没有带参数的函数,认为城没有显式说明的类型 

   
-fthis-is-varialble 
  就是向传统c++看齐,可以使用this当一般变量使用. 
   
-fcond-mismatch 
  允许条件表达式的第二和第三参数类型不匹配,表达式的值将为void类型 
   
-funsigned-char 
-fno-signed-char 
-fsigned-char 
-fno-unsigned-char 
  这四个参数是对char类型进行设置,决定将char类型设置成unsigned char(前两个参 
数)或者 signed char(后两个参数) 
   
-include file 
  包含某个代码,简单来说,就是便以某个文件,需要另一个文件的时候,就可以用它设 
定,功能就相当于在代码中使用#include<filename> 
  例子用法: 
  gcc hello.c -include /root/pianopan.h 
   
-imacros file 
  将file文件的宏,扩展到gcc/g++的输入文件,宏定义本身并不出现在输入文件中 
   
-Dmacro 
  相当于C语言中的#define macro 
   
-Dmacro=defn 
  相当于C语言中的#define macro=defn 
   
-Umacro 
  相当于C语言中的#undef macro 
-undef 
  取消对任何非标准宏的定义 
   
-Idir 
  在你是用#include"file"的时候,gcc/g++会先在当前目录查找你所制定的头文件,如 
果没有找到,他回到缺省的头文件目录找,如果使用-I制定了目录,他 
  回先在你所制定的目录查找,然后再按常规的顺序去找. 
  对于#include<file>,gcc/g++会到-I制定的目录查找,查找不到,然后将到系统的缺 
省的头文件目录查找 
   
-I- 
  就是取消前一个参数的功能,所以一般在-Idir之后使用 
   
-idirafter dir 
  在-I的目录里面查找失败,讲到这个目录里面查找. 
   
-iprefix prefix 
-iwithprefix dir 
  一般一起使用,当-I的目录查找失败,会到prefix+dir下查找 
   
-nostdinc 
  使编译器不再系统缺省的头文件目录里面找头文件,一般和-I联合使用,明确限定头 
文件的位置 
   
-nostdin C++ 
  规定不在g++指定的标准路经中搜索,但仍在其他路径中搜索,.此选项在创libg++库 
使用 
   
-C 
  在预处理的时候,不删除注释信息,一般和-E使用,有时候分析程序,用这个很方便的 

   
-M 
  生成文件关联的信息。包含目标文件所依赖的所有源代码你可以用gcc -M hello.c 
来测试一下,很简单。 
   
-MM 
  和上面的那个一样,但是它将忽略由#include<file>造成的依赖关系。 
   
-MD 
  和-M相同,但是输出将导入到.d的文件里面 
   
-MMD 
  和-MM相同,但是输出将导入到.d的文件里面 
   
-Wa,option 
  此选项传递option给汇编程序;如果option中间有逗号,就将option分成多个选项,然 
后传递给会汇编程序 
   
-Wl.option 
  此选项传递option给连接程序;如果option中间有逗号,就将option分成多个选项,然 
后传递给会连接程序. 
   
-llibrary 
  制定编译的时候使用的库 
  例子用法 
  gcc -lcurses hello.c 
  使用ncurses库编译程序 
   
-Ldir 
  制定编译的时候,搜索库的路径。比如你自己的库,可以用它制定目录,不然 
  编译器将只在标准库的目录找。这个dir就是目录的名称。 
   
-O0 
-O1 
-O2 
-O3 
  编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高  
     
-g 
  只是编译器,在编译的时候,产生调试信息。 
   
-gstabs 
  此选项以stabs格式声称调试信息,但是不包括gdb调试信息. 
   
-gstabs+ 
  此选项以stabs格式声称调试信息,并且包含仅供gdb使用的额外调试信息. 
   
-ggdb 
  此选项将尽可能的生成gdb的可以使用的调试信息. 
-static 
  此选项将禁止使用动态库,所以,编译出来的东西,一般都很大,也不需要什么 
动态连接库,就可以运行. 
-share 
  此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库. 
-traditional 
  试图让编译器支持传统的C语言特性

http://www.cppblog.com/SEMAN/archive/2005/11/30/1440.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Ubuntu Linux gcc Werror