為什麼大多數程序主函數都return 0; 不return 1; ?


無論 C / C++,從 main 函數返回的效果都相當於調用 exit 函數,main 的返回值會作為傳給 exit 函數的參數。

exit 對於參數的說明是這樣的:

Finally, control is returned to the host environment. If the value of status is zero or
EXIT_SUCCESS, an implementation-defined form of the status successful termination is
returned. If the value of status is EXIT_FAILURE, an implementation-defined form
of the status unsuccessful termination is returned. Otherwise the status returned is
implementation-defined.

  • 如果參數為 0 或者 EXIT_SUCCESS,向外部環境報告程序運行圓滿結束
  • 如果參數為 EXIT_FAILURE,向外部環境報告程序運行以失敗告終
  • 如果參數為其它值,效果由實現定義

所以,return 0 是有確定語義的返回方式;而 return 1 則不具備可移植性


時間線:

  • 1972~1973,C 語言定型,用於開發 Unix on PDP-11。
  • 1974 年,Unix version 5 發布,「main() 返回0表示成功」的習俗至少從這時就定下來了。
  • 1978 年,Intel 8086 上市
  • 1981 年,IBM PC 上市
  • 1982 年,PC 上的第一個 C 編譯器(Lattice C - Wikipedia)發布

因此,「x86 上 return 0 效率更高」不是「C 語言習慣用 return 0 表示成功」的原因。


成功只有一種,失敗卻有2147483647種。這就是為什麼成功是0。


其實不是大多數,而應該是幾乎所有,,,,

原因就是0代表正確,成功完成……

而非0代表執行出錯了。

儘管現代的程序一般不需要用這種拙劣的方式來傳遞錯誤信息了,例如我們有標準錯誤輸出什麼的。但是這個約定依然存在,如果你隨便亂返回非零值,那麼某些東西就可能認為你是異常的。

舉幾個Windows操作系統的栗子。

當你使用cmd執行你的程序的時候(假定你的程序是控制台程序),有一個內部命令可以根據你程序返回的錯誤值來決定下一步的操作,如:IF ERRORLEVEL 1 xxxxxx

這個其實是從DOS一直繼承過來的一個DOS內部命令。

當你使用任務計劃程序(計算機管理系統工具任務計劃程序)執行你的程序的時候,如果你的程序最終的返回值不是0,則任務計劃程序會認為執行失敗了,可以在日誌和上一次運行結果裡面看到。

當然,Windows/DOS所有的外部命令如果執行失敗都會返回非零值,絕大多數控制台程序在正常情況下都會返回零值,.NET控制台應用程序如果出現沒有處理的異常,會返回非零值。


shell 定義了返回 0 值為成功,所有的批處理類應用都依賴程序返回 0 來判斷程序正常運行。

例如 Makefile 遇到返回非 0 值的進程會停止任務。

所以成功運行必須返回 0 。至於其它返回值則沒有定義。

程序內部函數返回什麼都可以,但一旦返回到操作系統,那個返回值必須用 0 代表成功。


補充下 @邱昊宇 說的「無論 C / C++,從 main 函數返回的效果都相當於調用 exit 函數,main 的返回值會作為傳給 exit 函數的參數。」

以下引用自ISO/IEC 14882:2014(E)§3.6.2 P59

A return statement in main has the e?ect of leaving the main function (destroying any objects with automatic storage duration) and calling std::exit with the return value as the argument. If control reaches the end of main without encountering a return statement, the e?ect is that of executing

return 0;


底下答案都挺好,但是忽略了一點,題主說的主函數,所以返回0,還表示系統退出的意思。一般命令行系統都這樣設計


因為一個程序正確結束,返回 0。異常或者錯誤退出返回非 0 ,非 0 的數字被當作錯誤碼用。

C 的主函數 return 0 表示默認情況下應該返回正確結束的 Code,如果你返回 1,雖然你的程序沒出現錯誤,但是被其他進程調用的時候 可能因為返回的非 0 而被認為出錯了。


return 0 為是Unix 時代的傳來風格.

很多系統調用里-1是錯誤, 0是成功,如果與文件IO相關大於往往是FD或者長度.

這樣一個返回值能有雙重含意


因為0表示成功,你的程序如果沒出錯的話,估計也不會故意的返回錯誤吧?!


#define EXIT_SUCCESS 0

#define EXIT_FAILURE 1


成功只有一種。失敗有千千萬個原因。


返回碼不管是Windows還是UNIX都約定返回0表示成功,C庫當中的許多函數也是這樣的,因為要用二值邏輯的話,只有0和非0的區別,C之類的大多數語言當中都會把非0當作TRUE,而把0當作FALSE。而返回碼顯然需要能表示許多不同的出錯情況。

所以只有這麼寫了才能在shell當中寫

run_some_command echo "succ"

其實這也只能算是大多數的情況,某些程序會用不同返回值表示不同的運行結果,比如grep會用返回1來表示沒有匹配成功(跟一般理解的失敗略有區別),而Linux的init.d腳本中,則會在執行status命令的時候,用不同的返回碼錶示服務的不同狀態。返回碼對於shell來說是一個非常重要的返回值。


這裡似乎沒有人給出正確答案......

最高票答案依然沒有回答出「為什麼規定0表示運行圓滿結束」;「0可移植而1不可移植」是結果而不是原因。

其實用0表示「成功」是UNIX哲學 ------ 沒有消息就是好消息:0,表示「沒有」,即「沒有任何問題」。

系統問程序:你運行是否有任何問題?

程序回復:沒有任何問題 ----- 即0,表示運行一切順利。


你要是故意寫return 1;

我懷疑修bug的會罵人……


不光可以返回0,1,還可以返回 -128 ... -2 -1 0 1 2 3 4 5...127

0表示程序執行成功,沒什麼可說的了

其他的 12345.. 你可以自己定義錯誤編號

在unix下的shell里調用可執行文件,$?變數就是這個返回值

或者是一個多進程程序

主進程啟動子進程後根據子進程的返回值來判斷

當然這個可能不夠,因為子進程會因為core dump沒有返回值,這個時候要看

你可以根據返回值做不同處理

這個返回值在你只會雙擊執行的時候沒什麼卵用

在寫void main() 的時候會產生編譯錯誤

用途是在大規模的自動化腳本里控制流程

就和你調用一個函數之後要檢查返回值一樣


是因為彙編的緣故,return 0效率更高一些。後來的晶元性能提高了,0和1的差距就沒那麼大了。但是這個規矩遺留下來,很多彙編甚至return 0是一句(因為有專門的0寄存器),return 1是兩句。(但有的不是這樣的)在當年1byte ROM一寸金的年代。你多一句彙編基本可以和你明天還能不能來上班劃等號的。

看了幾個答案,署名都是資深程序員,回答都相當離譜,還說啥移植性的。。。。其實也很顯然,現在很多應用程序員都被高集成化的編譯器給慣壞了,這麼簡單的問題反而不會了。

更新

我看有的人沒搞明白彙編和C的關係,一般彙編效率是C語言的3倍,我也見過有的大牛寫出來和彙編效率差不多的C語言,但是通用性極差,只能在特殊場合使用。當然彙編佔用空間是要更少的。

C語言通過編譯器變成彙編(帶地址標籤)中間文件,最終生成hex 也就是機器碼了(不帶地址標籤)。

函數return 主要分三個部分,一個是出棧,一個是賦返回值,一個是付PC指針,這其中SP(stack pointer register)也會發生變化,跳轉。其他的就不說了,就說賦值這塊。0對於CPU很容易得到的,實際上就是接地么。那麼如果有個0寄存器,或者編程者自己犧牲一個寄存器常為0,通常就是不設置,一般cpu初始化通用寄存器都是全為0的,後來也有是隨機值的,但是少見一些。具體CPU如何Reset的,這些怎麼變成0的,我就不講了,這裡很多人是搞應用編程的,對半導體設計一般不熟悉。

這裡拿出808x的CPU指令集,這是複雜指令集的,一般常見的通用寄存器有A X B C D E H L。如果我需要將返回值賦成1,我需要調用MOV指令他需要4個時鐘周期,而我要用XCH的話,只需要一半的時間。簡單指令集的一般是調用LD,也差不多我就不貼了,所有簡單指令集的CPU都是帶常0寄存器的。我說的效率就體現在這裡,很多編譯器會用B C去作為返回值存儲器,那返回0就會少一句彙編指令,效果就更好了。有人會問為啥用B C,因為A X 通常作為參數用的存儲器,用的比較頻繁,當然我個人習慣用A X傳返回值,這樣效率高,這個就見仁見智了。


返回的一般是錯誤代碼,0表示沒有錯誤


當初如果用EXIT_SUCCESS=42就有趣了……


你如果用CLion運行程序,然後某個地方寫錯了導致你的程序炸了,那你就能在終端里看到各種奇奇怪怪的return code了


推薦閱讀:

為什麼使用gcc編譯代碼後局部數組變數的初始值消失了?
怎麼來學習c++?
學習完 C++ Primer 能做什麼項目練手或者看什麼好的開源項目源碼?
關於C++宏定義的一個疑問?
我們用的計算機語言底層都是用什麼寫的?

TAG:編程 | C編程語言 | 計算機科學 | CC |