如果 main 函數的末尾沒有 return 語句將會有什麼影響

背景簡介

本文是前段在知乎回答的一個問題,覺得蠻重要的,重新編撰發佈如下。

原問題為:

"c語言中,如果main函數的末尾沒有return語句將會有什麼影響?":

我是準大一,學計算機的,剛剛接觸計算機,萌新求解答

原回答請參考這裡: https://www.zhihu.com/question/338814178/answer/785578903

問題的本質

回答這個問題其實只要理解一個東西就行了:

那就是帶有返回值的函數請務必提供返回值,這個是基本約定也是編程習慣,如果大家都遵守,你不遵守,各種奇葩和頭疼的後果就遲早會來,不管是 main 也好,其他函數也好。

所以,準大一這個時候一定要從現在開始養成習慣,遵守語言的基本約定。

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

很多同學寫例子,也有這麼寫的?

void main(void) { }

實際上,完整的 main 聲明還有第三個參數 env,這裡不做展開。

C 語言各標準差異以及靜態檢測方法

這種可以用 -Wall 檢查出來:

$ echo 'void main(void) {}' | gcc -Wall -x c - -
<stdin>:1:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
/<stdin>

如果用 int 默認檢查不出來 return value ,默認是兼容 c11 的 gnu11:

$ echo 'int main(void) {}' | gcc -Wall -x c - -
$ echo 'int main(void) {}' | gcc -Wall -std=gnu11 -x c - -

試了下,c99 之後都是沒有提示問題。但是 c90 以及之前都提示需要加返回值:

$ echo 'int main(void) {}' | gcc -Wall -std=c90 -x c - -
<stdin>: In function ‘main’:
<stdin>:1:1: warning: control reaches end of non-void function [-Wreturn-type]
/<stdin>/<stdin>

考慮到兼容性,建議務必養成寫法上的習慣。由於 main 稍微特殊些,c99 默認處理了,但是對於其他函數還是要自己加,不做處理的話,是有很大風險的。

對於 c99 以及之後的版本,對普通函數還是會做檢查。如果有的寫,有的不寫,不一致的話久而久之習慣就很難養成了。

$ echo 'int test(void) {}; int main(void) { test(); }' | gcc -Wall -std=c99 -x c - -
<stdin>: In function ‘test’:

<stdin>:1:1: warning: control reaches end of non-void function [-Wreturn-type]
/<stdin>/<stdin>

由於人總會出錯,所以,在編譯的 cflags 裡頭,建議強制加上 -Wall -Werror,在遇到這類錯誤是強制退出,而不僅僅是警告。當然,對於已經存在的項目,prove-in-use 的情況下,建議保留之前的默認配置選項,除非要確實投入很多精力去重構。

$ echo 'int main(void) {}' | gcc -Wall -Werror -std=c90 -x c - -
<stdin>: In function ‘main’:
<stdin>:1:1: error: control reaches end of non-void function [-Werror=return-type]
cc1: all warnings being treated as errors
/<stdin>/<stdin>

關於返回值的含義

需要注意的是,默認情況下,沒有錯誤,就是 return 0,而不是 return 1。

完整的模板:

int main(int argc, char *argv[])
{
return 0;
}

上面多次提到了後果和風險,為什麼?因為檢查函數和程序返回值是一個最最基礎的操作。如果不按常理返回正確的返回值,後果是,後續對該值的檢查所做出的所有動作都可能不可預知。

這個值是怎麼體現的呢?

$ echo -e 'int main(void){ return 0; }' | gcc -Wall -Werror -std=c99 -O0 -x c - - 

$ ./a.out
$ echo $?
0
$ echo -e 'int main(void){ return 100; }' | gcc -Wall -Werror -std=c99 -O0 -x c - -
$ ./a.out
$ echo $?
100

比如說,在 Shell 編程中通常會在程序執行完,立即檢查返回值,然後決定接下去做什麼操作?

if [ $? -eq 0 ]; then echo 'Success'; else echo 'Failure'; fi


分享到:


相關文章: