程序员是追求完美的一族,即使是一般的程序员大多也都不想看到自己的程序中有甚至那么一点点的瑕疵。遇到任意一条编译器警告都坚决不放过。有人会说:我们可以使用比编译器更加严格的静态代码检查工具,如splint。 这个建议也很不错。不过lint工具使用起来较繁琐,有时候还需要记住一些特定符号并插入到你自己的代码中才行,门槛较高,这也让很多人止步于此。那么我 们就从此放弃么?不,如今的编译器做得都很好,它可以帮助我们的找到绝大多数可能出现问题的代码,前提是你要学会控制编译器去找到这些问题代码,而熟悉编 译器的警告选项恰恰是体现控制力的好方法。当你可以自如控制编译器警告输出的时候,你就算是'入道'了,同时你对语言的理解也更进一步了。r7tLinux联盟 有人说:我就是用一个-Wall选项就可以了,一般选手可以这么做,而且他可以不知道-Wall会跟踪哪些类型的问题;但是高级选手是不会只使用- Wall的,他会把每条警告都研究的很透彻,会在Makefile中列出他想让编译器输出哪些类型的警告以替代-Wall,他会屏蔽掉那些对他的代码'毫 无用处'的警告(很可能他使用了编译器对语言的扩展功能),他会有个和编译器交流的过程。r7tLinux联盟 俗话说:'工欲善其事,必先利其器',一直在工作中使用GNU C编译器(以下简称GCC),这里对GCC的一些警告选项细致的分析,并列举几个简单的例子[注1]供分析参考。r7tLinux联盟 1. -Wall集合警告选项r7tLinux联盟 我们平时可能大多数情况只使用-Wall编译警告选项,实际上-Wall选项是一系列警告编译选项的集合。下面逐一分析这一集合中的各个选项:r7tLinux联盟 [-Wchar-subscripts]r7tLinux联盟 如果数组使用char类型变量做为下标值的话,则发出警告。因为在某些平台上char可能默认为signed char,一旦溢出,就可能导致某些意外的结果。r7tLinux联盟 e.g.r7tLinux联盟 /* test_signed_char.c */r7tLinux联盟 #i nclude r7tLinux联盟 int main () {r7tLinux联盟 char c = 255; // 我们以为char是无符号的,其范围应该是[0,255]r7tLinux联盟 int i = 0;r7tLinux联盟 int a[256];r7tLinux联盟 for (i = 0; i < 256; i++) {r7tLinux联盟 a[i] = 1;r7tLinux联盟 }r7tLinux联盟 printf("%d\n", c); // 我们期待输出255r7tLinux联盟 printf("%d\n", a[c]); // 我们期待输出1r7tLinux联盟 printf("%d\n", a[255]);r7tLinux联盟 return 0;r7tLinux联盟 }r7tLinux联盟 gcc -Wchar-subscripts test_signed_char.cr7tLinux联盟 test_signed_char.c: In function `main':r7tLinux联盟 test_signed_char.c:13: warning: array subscript has type `char'r7tLinux联盟 其输出结果:r7tLinux联盟 -1r7tLinux联盟 -4197476r7tLinux联盟 1r7tLinux联盟 从输出结果来看Solaris 9/gcc 3.2上char默认实现类型为signed char;在Windows XP/gcc-3.4.2上也是一样。r7tLinux联盟 Windows上的输出结果:r7tLinux联盟 -1r7tLinux联盟 16 (随机值)r7tLinux联盟 1r7tLinux联盟 [-Wcomment]r7tLinux联盟 当'/*'出现在 '/* ... */'注释中,或者'\'出现在'// ...'注释结尾处时,使用-Wcomment会给出警告。不要小觑这些马虎代码,它很可能会影响程序的运行结果。如下面的例子:r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_comment.cr7tLinux联盟 * gcc -Wcomment test_comment.cr7tLinux联盟 */r7tLinux联盟 #i nclude r7tLinux联盟 int main() {r7tLinux联盟 int a = 1;r7tLinux联盟 int b = 2;r7tLinux联盟 int c = 0; // ok just test\r7tLinux联盟 c = a + b;r7tLinux联盟 /*r7tLinux联盟 * 这里我们期待c = 3r7tLinux联盟 * /* 但实际上输出c = 0r7tLinux联盟 */r7tLinux联盟 printf("the c is %d\n", c);r7tLinux联盟 return 0;r7tLinux联盟 }r7tLinux联盟 gcc -Wcomment test_comment.cr7tLinux联盟 test_comment.c:10:30: warning: multi-line commentr7tLinux联盟 test_comment.c:15:12: warning: "/*" within commentr7tLinux联盟 输出:r7tLinux联盟 the c is 0r7tLinux联盟 [-Wformat]r7tLinux联盟 检查printf和scanf等格式化输入输出函数的格式字符串与参数类型的匹配情况,如果发现不匹配则发出警告。某些时候格式字符串与参数类型的不匹配会导致程序运行错误,所以这是个很有用的警告选项。r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_format.cr7tLinux联盟 */r7tLinux联盟 #i nclude r7tLinux联盟 int main() {r7tLinux联盟 long l = 1;r7tLinux联盟 double d = 55.67;r7tLinux联盟 printf("%d\n", l);r7tLinux联盟 printf("%d\n", d);r7tLinux联盟 return 0;r7tLinux联盟 }r7tLinux联盟 gcc -Wformat test_format.cr7tLinux联盟 test_format.c: In function `main':r7tLinux联盟 test_format.c:10: warning: int format, long int arg (arg 2)r7tLinux联盟 test_format.c:11: warning: int format, double arg (arg 2)r7tLinux联盟 输出:r7tLinux联盟 1r7tLinux联盟 1078711746r7tLinux联盟 [-Wimplicit]r7tLinux联盟 该警告选项实际上是-Wimplicit-int和-Wimplicit-function-declaration两个警告选项的集合。前者在声明函数却未指明函数返回类型时给出警告,后者则是在函数声明前调用该函数时给出警告。r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_implicit.cr7tLinux联盟 */r7tLinux联盟 #i nclude r7tLinux联盟 add(int a, int b) { //函数没有声明返回类型r7tLinux联盟 return a + b;r7tLinux联盟 }r7tLinux联盟 int test() {r7tLinux联盟 int a = 0;r7tLinux联盟 int b = 0;r7tLinux联盟 int c = 0;r7tLinux联盟 int d = 0;r7tLinux联盟 c = add(a, b);r7tLinux联盟 d = sub(a, b); //未声明sub的函数原型r7tLinux联盟 return 0;r7tLinux联盟 }r7tLinux联盟 gcc -Wimplicit -c test_implicit.cr7tLinux联盟 test_implicit.c:7: warning: return type defaults to `int'r7tLinux联盟 test_implicit.c: In function `test':r7tLinux联盟 test_implicit.c:18: warning: implicit declaration of function `sub'r7tLinux联盟 [-Wmissing-braces]r7tLinux联盟 当聚合类型或者数组变量的初始化表达式没有'充分'用括号{}括起时,给出警告。文字表述很难理解,举例说明则清晰些。看下面的例子:r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_missing_braces.cr7tLinux联盟 */r7tLinux联盟 struct point {r7tLinux联盟 int x;r7tLinux联盟 int y;r7tLinux联盟 };r7tLinux联盟 struct line {r7tLinux联盟 struct point start;r7tLinux联盟 struct point end;r7tLinux联盟 };r7tLinux联盟 typedef struct line line;r7tLinux联盟 int main() {r7tLinux联盟 int array1[2][2] = {11, 12, 13, 14};r7tLinux联盟 int array2[2][2] = {{11, 12}, {13, 14}}; // okr7tLinux联盟 line l1 = {1, 1, 2, 2};r7tLinux联盟 line l2 = {{2, 2}, {3, 3}}; // okr7tLinux联盟 return 0;r7tLinux联盟 }r7tLinux联盟 gcc -Wmissing-braces test_missing_braces.cr7tLinux联盟 test_missing_braces.c: In function `main':r7tLinux联盟 test_missing_braces.c:19: warning: missing braces around initializerr7tLinux联盟 test_missing_braces.c:19: warning: (near initialization for `array1[0]')r7tLinux联盟 test_missing_braces.c:21: warning: missing braces around initializerr7tLinux联盟 test_missing_braces.c:21: warning: (near initialization for `l1.start')r7tLinux联盟 [-Wparentheses]r7tLinux联盟 这是一个很有用的警告选项,它能帮助你从那些看起来语法正确但却由于操作符优先级或者代码结构'障眼'而导致错误运行的代码中解脱出来。好长的一个长句,还是看例子理解吧!:)r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_parentheses.cr7tLinux联盟 * gcc -Wparentheses test_parentheses.cr7tLinux联盟 */r7tLinux联盟 #i nclude r7tLinux联盟 int main() {r7tLinux联盟 int a = 1;r7tLinux联盟 int b = 1;r7tLinux联盟 int c = 1;r7tLinux联盟 int d = 1;r7tLinux联盟 if (a && b || c) { // 人们很难记住逻辑操作符的操作顺序,所以编译器建议加上()r7tLinux联盟 ;r7tLinux联盟 }r7tLinux联盟 if (a == 12)r7tLinux联盟 if (b)r7tLinux联盟 d = 9; r7tLinux联盟 elser7tLinux联盟 d = 10; //从代码的缩进上来看,这句仿佛是if (a == 12)的else分支r7tLinux联盟 printf("the d is %d\n", d); //期待d = 10, 而结果却是1r7tLinux联盟 return 0;r7tLinux联盟 }r7tLinux联盟 gcc -Wparentheses test_parentheses.cr7tLinux联盟 test_parentheses.c: In function `main':r7tLinux联盟 test_parentheses.c:13: warning: suggest parentheses around && within ||r7tLinux联盟 test_parentheses.c:17: warning: suggest explicit braces to avoid ambiguous `else'r7tLinux联盟 输出:r7tLinux联盟 the d is 1r7tLinux联盟 [-Wsequence-point]r7tLinux联盟 关于顺序点(sequence point),在C标准中有解释,不过很晦涩。我们在平时编码中尽量避免写出与实现相关、受实现影响的代码便是了。而-Wsequence-point选项恰恰可以帮我们这个忙,它可以帮我们查出这样的代码来,并给出其警告。r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_sequence_point.cr7tLinux联盟 * gcc -Wsequence-point test_sequence_point.cr7tLinux联盟 */r7tLinux联盟 #i nclude r7tLinux联盟 int main() {r7tLinux联盟 int i = 12;r7tLinux联盟 i = i--;r7tLinux联盟 printf("the i is %d\n", i);r7tLinux联盟 return 0;r7tLinux联盟 }r7tLinux联盟 gcc -Wsequence-point test_sequence_point.cr7tLinux联盟 test_sequence_point.c: In function `main':r7tLinux联盟 test_sequence_point.c:10: warning: operation on `i' may be undefinedr7tLinux联盟 在两个平台上给出的编译警告都是一致的,但是输出结果却大相径庭。r7tLinux联盟 Solaris输出:r7tLinux联盟 the i is 11r7tLinux联盟 Windows输出:r7tLinux联盟 the i is 12r7tLinux联盟 类似的像这种与顺序点相关的代码例子有:r7tLinux联盟 i = i++;r7tLinux联盟 a[i] = b[i++] r7tLinux联盟 a[i++] = ir7tLinux联盟 等等...r7tLinux联盟 [-Wswitch]r7tLinux联盟 这个选项的功能浅显易懂,通过文字描述也可以清晰的说明。当以一个枚举类型(enum)作为switch语句的索引时但却没有处理default情况,或者没有处理所有枚举类型定义范围内的情况时,该选项会给处警告。r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_switch1.cr7tLinux联盟 */r7tLinux联盟 enum week {r7tLinux联盟 SUNDAY,r7tLinux联盟 MONDAY,r7tLinux联盟 TUESDAY /* only an example , we omitted the others */r7tLinux联盟 };r7tLinux联盟 int test1() {r7tLinux联盟 enum week w = SUNDAY;r7tLinux联盟 switch(w) {r7tLinux联盟 case SUNDAY:r7tLinux联盟 break; // without default or the other case handlingsr7tLinux联盟 };r7tLinux联盟 return 0;r7tLinux联盟 }r7tLinux联盟 int test2() { // Ok, won't invoke even a warningr7tLinux联盟 enum week w = SUNDAY;r7tLinux联盟 switch(w) {r7tLinux联盟 case SUNDAY:r7tLinux联盟 break;r7tLinux联盟 default:r7tLinux联盟 break; r7tLinux联盟 };r7tLinux联盟 return 0;r7tLinux联盟 }r7tLinux联盟 int test3() { // Ok, won't invoke even a warningr7tLinux联盟 enum week w = SUNDAY;r7tLinux联盟 switch(w) {r7tLinux联盟 case SUNDAY:r7tLinux联盟 break;r7tLinux联盟 case MONDAY:r7tLinux联盟 break;r7tLinux联盟 case TUESDAY:r7tLinux联盟 break; r7tLinux联盟 };r7tLinux联盟 return 0;r7tLinux联盟 }r7tLinux联盟 gcc -Wswitch -c test_switch.cr7tLinux联盟 test_switch.c: In function `test1':r7tLinux联盟 test_switch.c:16: warning: enumeration value `MONDAY' not handled in switchr7tLinux联盟 test_switch.c:16: warning: enumeration value `TUESDAY' not handled in switchr7tLinux联盟 [-Wunused]r7tLinux联盟 -Wunused是-Wunused-function、-Wunused-label、-Wunused-variable、-Wunused-value选项的集合,-Wunused-parameter需单独使用。r7tLinux联盟 (1) -Wunused-function用来警告存在一个未使用的static函数的定义或者存在一个只声明却未定义的static函数,参见下面例子中的func1和func2;r7tLinux联盟 (2) -Wunused-label用来警告存在一个使用了却未定义或者存在一个定义了却未使用的label,参加下面例子中的func3和func7;r7tLinux联盟 (3) -Wunused-variable用来警告存在一个定义了却未使用的局部变量或者非常量static变量;参见下面例子中func5和var1;r7tLinux联盟 (4) -Wunused-value用来警告一个显式计算表达式的结果未被使用;参见下面例子中func6r7tLinux联盟 (5) -Wunused-parameter用来警告一个函数的参数在函数的实现中并未被用到,参见下面例子中func4。r7tLinux联盟 下面是一个综合的例子r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_unused.cr7tLinux联盟 */r7tLinux联盟 static void func1(); //to prove function used but never definedr7tLinux联盟 static void func2(); //to prove function defined but not usedr7tLinux联盟 static void func3(); //to prove label used but never definedr7tLinux联盟 static void func7(); //to prove label defined but never usedr7tLinux联盟 static void func4(int a); //to prove parameter declared but not usedr7tLinux联盟 static void func5(); //to prove local variable defined but not usedr7tLinux联盟 static void func6(); //to prove value evaluated but not usedr7tLinux联盟 static int var1;r7tLinux联盟 void test() {r7tLinux联盟 func1();r7tLinux联盟 func3();r7tLinux联盟 func4(4);r7tLinux联盟 func5();r7tLinux联盟 func6();r7tLinux联盟 }r7tLinux联盟 static void func2() {r7tLinux联盟 ; // do nothingr7tLinux联盟 }r7tLinux联盟 static void func3() {r7tLinux联盟 goto over;r7tLinux联盟 }r7tLinux联盟 static void func4(int a) {r7tLinux联盟 ; // do nothingr7tLinux联盟 }r7tLinux联盟 static void func5() {r7tLinux联盟 int a = 0;r7tLinux联盟 }r7tLinux联盟 static void func6() {r7tLinux联盟 int a = 0;r7tLinux联盟 int b = 6;r7tLinux联盟 a + b;r7tLinux联盟 }r7tLinux联盟 gcc -Wunused-parameter -c test_unused.c //如果不是用-Wunused-parameter,则func4函数将不被警告。r7tLinux联盟 test_unused.c: In function `func3':r7tLinux联盟 test_unused.c:30: label `over' used but not definedr7tLinux联盟 test_unused.c: In function `func7':r7tLinux联盟 test_unused.c:35: warning: deprecated use of label at end of compound statementr7tLinux联盟 test_unused.c:34: warning: label `over' defined but not usedr7tLinux联盟 test_unused.c: In function `func4':r7tLinux联盟 test_unused.c:37: warning: unused parameter `a'r7tLinux联盟 test_unused.c: In function `func5':r7tLinux联盟 test_unused.c:42: warning: unused variable `a'r7tLinux联盟 test_unused.c: In function `func6':r7tLinux联盟 test_unused.c:48: warning: statement with no effectr7tLinux联盟 test_unused.c: At top level:r7tLinux联盟 test_unused.c:6: warning: `func1' used but never definedr7tLinux联盟 test_unused.c:25: warning: `func2' defined but not usedr7tLinux联盟 test_unused.c:14: warning: `var1' defined but not usedr7tLinux联盟 [-Wuninitialized]r7tLinux联盟 该警告选项用于检查一个局部自动变量在使用之前是否已经初始化了或者在一个longjmp调用可能修改 一个non-volatile automatic variable时给出警告。目前编译器还不是那么smart,所以对有些可以正确按照程序员的意思运行的代码还是给出警告。而且该警告选项需要和'- O'选项一起使用,否则你得不到任何uinitialized的警告。r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_uninitialized.cr7tLinux联盟 */r7tLinux联盟 int test(int y) {r7tLinux联盟 int x;r7tLinux联盟 switch (y) {r7tLinux联盟 case 1:r7tLinux联盟 x = 11;r7tLinux联盟 break;r7tLinux联盟 case 2:r7tLinux联盟 x = 22;r7tLinux联盟 break;r7tLinux联盟 case 3:r7tLinux联盟 x = 33;r7tLinux联盟 break;r7tLinux联盟 }r7tLinux联盟 return x;r7tLinux联盟 }r7tLinux联盟 gcc -Wuninitialized -O -c test_uninitialized.cr7tLinux联盟 test_uninitialized.c: In function `test':r7tLinux联盟 test_uninitialized.c:6: warning: `x' might be used uninitialized in this functionr7tLinux联盟 2、非-Wall集合警告选项r7tLinux联盟 以下讨论的这些警告选项并不包含在-Wall中,需要程序员显式添加。r7tLinux联盟 [-Wfloat-equal]r7tLinux联盟 该项用来检查浮点值是否出现在相等比较的表达式中。r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_float_equal.cr7tLinux联盟 */r7tLinux联盟 void test(int i) {r7tLinux联盟 double d = 1.5;r7tLinux联盟 if (d == i) {r7tLinux联盟 ;r7tLinux联盟 }r7tLinux联盟 }r7tLinux联盟 gcc -Wfloat-equal -c test_float_equal.cr7tLinux联盟 test_float_equal.c: In function `test':r7tLinux联盟 test_float_equal.c:8: warning: comparing floating point with == or != is unsafer7tLinux联盟 [-Wshadow]r7tLinux联盟 当局部变量遮蔽(shadow)了参数、全局变量或者是其他局部变量时,该警告选项会给我们以警告信息。r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_shadow.cr7tLinux联盟 */r7tLinux联盟 int g;r7tLinux联盟 void test(int i) {r7tLinux联盟 short i;r7tLinux联盟 double g;r7tLinux联盟 }r7tLinux联盟 gcc -Wshadow -c test_shadow.cr7tLinux联盟 test_shadow.c: In function `test':r7tLinux联盟 test_shadow.c:9: warning: declaration of `i' shadows a parameterr7tLinux联盟 test_shadow.c:10: warning: declaration of `g' shadows a global declarationr7tLinux联盟 test_shadow.c:6: warning: shadowed declaration is herer7tLinux联盟 [-Wbad-function-cast]r7tLinux联盟 当函数(准确地说应该是函数返回类型)被转换为非匹配类型时,均产生警告。r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_bad_func_case.cr7tLinux联盟 */r7tLinux联盟 int add(int a, int b) {r7tLinux联盟 return a+b;r7tLinux联盟 }r7tLinux联盟 void test() {r7tLinux联盟 char *p = (char*)add(1, 13);r7tLinux联盟 }r7tLinux联盟 gcc -Wbad-function-cast -c test_bad_func_case.cr7tLinux联盟 test_bad_func_case.c: In function `test':r7tLinux联盟 test_bad_func_case.c:11: warning: cast does not match function typer7tLinux联盟 [-Wcast-qual]r7tLinux联盟 当去掉修饰源Target的限定词(如const)时,给出警告。r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_cast_qual.cr7tLinux联盟 */r7tLinux联盟 void test() {r7tLinux联盟 char c = 0;r7tLinux联盟 const char *p = &c;r7tLinux联盟 char *q;r7tLinux联盟 q = (char*)p;r7tLinux联盟 }r7tLinux联盟 gcc -Wcast-qual -c test_cast_qual.cr7tLinux联盟 test_cast_qual.c: In function `test':r7tLinux联盟 test_cast_qual.c:10: warning: cast discards qualifiers from pointer target typer7tLinux联盟 [-Wcast-align]r7tLinux联盟 这是个非常有用的选项,特别是对于在Solaris这样的对内存对齐校验的平台尤其重要。它用于在从对齐系数小的地址(如char*)转换为对齐系数大的地址(如int*)转换时给出警告。r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_cast_align.cr7tLinux联盟 */r7tLinux联盟 #i nclude r7tLinux联盟 int main() {r7tLinux联盟 char c = 1;r7tLinux联盟 char *p = &c; //okr7tLinux联盟 int *q = (int*)p; //bad align-castr7tLinux联盟 printf("the *q is %d\n", *q);r7tLinux联盟 return 0;r7tLinux联盟 }r7tLinux联盟 gcc -Wcast-align test_cast_align.cr7tLinux联盟 test_cast_align.c: In function `main':r7tLinux联盟 test_cast_align.c:9: warning: cast increases required alignment of target typer7tLinux联盟 输出:r7tLinux联盟 总线错误 ((主存储器)信息转储) //on Solaris 9r7tLinux联盟 [-Wsign-compare]r7tLinux联盟 在有符号数和无符号数进行值比较时,有符号数可能在比较之前被转换为无符号数而导致结果错误。使用该选项会对这样的情况给出警告。r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_sign_compare.cr7tLinux联盟 */r7tLinux联盟 #i nclude r7tLinux联盟 int main() {r7tLinux联盟 unsigned int i = 128;r7tLinux联盟 signed int j = -1;r7tLinux联盟 if (i < j) {r7tLinux联盟 printf("i < j\n");r7tLinux联盟 } else {r7tLinux联盟 printf("i > j\n");r7tLinux联盟 }r7tLinux联盟 return 0;r7tLinux联盟 }r7tLinux联盟 gcc -Wsign-compare test_sign_compare.cr7tLinux联盟 test_sign_compare.c: In function `main':r7tLinux联盟 test_sign_compare.c:10: warning: comparison between signed and unsignedr7tLinux联盟 输出:r7tLinux联盟 i < jr7tLinux联盟 [-Waggregate-return]r7tLinux联盟 如果一个函数返回一个聚合类型,如结构体、联合或者数组,该选项就会给出警告信息。较简单不举例了。r7tLinux联盟 [-Wmultichar]r7tLinux联盟 当我们写下如此代码时:char c = 'peter', 使用该选项会给出警告。这个选项是默认选项,你无需单独使用该选项,不过你可以使用-Wno-multichar来关闭这些警告信息,但是这可是不建议你 去做的。对于char c = 'peter'这样的代码的处理是与平台相关,不可移植的。r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_multichar.cr7tLinux联盟 */r7tLinux联盟 int main() {r7tLinux联盟 char c = 'peter';r7tLinux联盟 printf("c is %c\n", c);r7tLinux联盟 return 0;r7tLinux联盟 }r7tLinux联盟 但这里在Windows和Solaris平台输出的结果却一致:r7tLinux联盟 c is rr7tLinux联盟 [-Wunreachable-code]r7tLinux联盟 这个选项是一个检查冗余代码或疏忽代码好办法。它一旦检查到你的代码中有不可达的代码,就会发出警告。这些代码往往会存在潜在的危机。r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_unreachable.cr7tLinux联盟 */r7tLinux联盟 int test(char c) {r7tLinux联盟 if (c < 256) {r7tLinux联盟 return 0;r7tLinux联盟 } else {r7tLinux联盟 return 1;r7tLinux联盟 }r7tLinux联盟 }r7tLinux联盟 gcc -Wunreachable-code -c test_unreachable.cr7tLinux联盟 test_unreachable.c: In function `test':r7tLinux联盟 test_unreachable.c:6: warning: comparison is always true due to limited range of data typer7tLinux联盟 test_unreachable.c:9: warning: will never be executedr7tLinux联盟 [-Wconvertion]r7tLinux联盟 由于原型定义而引起的定点和浮点数之间的隐式转换(强制转换)或者由有符号数和无符号数之间隐式转换转换引起的警告。r7tLinux联盟 e.g.r7tLinux联盟 /*r7tLinux联盟 * test_conversion.cr7tLinux联盟 */r7tLinux联盟 #i nclude r7tLinux联盟 void getdouble(double d) {r7tLinux联盟 ; // do nothingr7tLinux联盟 }r7tLinux联盟 int main() {r7tLinux联盟 unsigned int k;r7tLinux联盟 int n = 12;r7tLinux联盟 k = -1;r7tLinux联盟 k = (unsigned int)-1; // ok, explicit conversion ,no warningr7tLinux联盟 getdouble(n);r7tLinux联盟 return 0;r7tLinux联盟 }r7tLinux联盟 gcc -Wconversion test_conversion.cr7tLinux联盟 test_conversion.c: In function `main':r7tLinux联盟 test_conversion.c:15: warning: negative integer implicitly converted to unsigned typer7tLinux联盟 test_conversion.c:18: warning: passing arg 1 of `getdouble' as floating rather than integer due to prototyper7tLinux联盟 3、-Wtraditional和-Wr7tLinux联盟 这两个警告选项其实也都是一些组合(大部分都在上面提到过),前者用来在代码中使用了标准C不同于传统C的特性时,发出警告;后者也是针对一些事件打开一个警告集合。关于它们的说明具体可参见'Using the GNU Compiler Collection'。r7tLinux联盟
|