GCC:条件判断中赋值语句和函数结尾时无返回值的警告

  有下面很是经典的一个字符串复制程序。程序员

  test1.c数组

 1 #include <stdio.h>
 2 int main()
 3 {
 4     char str_t[]="This String comes from t";//初始化字符数组
 5     char str_s[]="This is an empty string  ";//初始化字符数组
 6     char *t=str_t;//初始化字符指针
 7     char *s=str_s;//初始化字符指针
 8     while(*s++=*t++)//*的优先级比++高,且为右结合,所以会将t的值逐个赋值给s,直到结果为'\0'
 9         ;
10     printf("%s\n%s\n",str_t,str_s);
11     //此处省略了返回值
12 }

  先用$gcc test1.c编译。编译成功,无提示。再用检查地更严格的-Wall选项试一试。函数

  $gcc test1.c -Wallspa

  编译器提示以下:指针

1 $ gcc test1.c -Wall
2 test1.c: In function ‘main’:
3 test1.c:8:2: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
4   while(*s++=*t++)//*的优先级比++高,且为右结合,所以会将t的值逐个赋值给s,直到结果为'\0'
5   ^
6 test1.c:12:1: warning: control reaches end of non-void function [-Wreturn-type]
7  }
8  ^

  咱们逐个进行分析。调试

  首先是 warning: suggest parentheses around assignment used as truth value (警告:建议在赋值语句周围使用小括号来代表“真值”)。这是由于咱们有语句while(*s++=*t++),在这种状况下,程序员实在是太容易把=和==弄混了。我曾经有一个程序调试了好久都没有发现错误,直到最后发现了这样一个错误:code

  while(s=‘\n’)blog

    ...;字符串

  在这种状况下,除非s老是等于'\n'这个非零值,所以除非while内部有跳转语句,这将会是一个死循环。GCC之因此在这里发出警告就是这个缘由,若是这样写编译器

  while((*s++=*t++)),就用括号代表了这是一个赋值语句而不是由于疏忽大意写的关系表达式,另外还有一些程序员喜欢把常量(或者说是右值放在==的左侧)好比:

    if('\n'==x);

这样在编译时若是不当心写成了=也由于编译器的检查(不能赋值)而发现错误,在编译时刻犯错总比在运行时刻犯错要好!

  总之在全部=和==可能混淆的语句中(尤为是if/while/for)若是开启了-Wall或者其它警告选项,GCC就会发出这样的警告,这个时候强烈建议你把GCC提示的地方检查一下!

  第二个警告是 warning: control reaches end of non-void function (警告:控制流到达返回值非void的函数结尾)。这是由于咱们定义了int main(),而结束时却没有使用return返回一个int产生的。在早期的K&R C中任何没有显式规定返回类型的函数都默认返回一个int值,任何没有显式返回的非void函数都会返回一个int值(实际上还有任何没有定义类型的变量都会被定义为int型变量,任何没有显式转换的malloc返回值都会被认为是char*……正是一些奇怪的定义),而在C++中,若是main函数结尾没有返回,则会自动加上return 0。这些也正是为何GCC会经过这个函数的缘由,在main()中返回数值的做用你们都是直到,不过若是这个警告出如今别的函数中就要注意了!

  好的,下面是改进事后的程序:

  test1.c

 1 #include <stdio.h>
 2 int main()
 3 {
 4     char str_t[]="This String comes from t";//初始化字符数组
 5     char str_s[]="This is an empty string  ";//初始化字符数组
 6     char *t=str_t;//初始化字符指针
 7     char *s=str_s;//初始化字符指针
 8     while((*s++=*t++))//*的优先级比++高,且为右结合,所以会将t的值逐个赋值给s,直到结果为'\0'
 9         ;
10     printf("%s\n%s\n",str_t,str_s);
11     return 0;
12 }

  从新用$gcc test1.c -Wall,发现没有刚才的警告了。

  编译器的警告虽然不是错误,可是不少都是介与正确和错误之间的哪些部分,虽然编译器的警告不能使咱们的程序百分之百正确,但会使咱们离这个目标愈来愈近,重视编译器的警告也是一个好程序员的习惯。

相关文章
相关标签/搜索