有下面很是經典的一個字符串複製程序。程序員
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,發現沒有剛纔的警告了。
編譯器的警告雖然不是錯誤,可是不少都是介與正確和錯誤之間的哪些部分,雖然編譯器的警告不能使咱們的程序百分之百正確,但會使咱們離這個目標愈來愈近,重視編譯器的警告也是一個好程序員的習慣。