main 是程序入口,其返回值向操作系統報告執行狀態。然而 void main() 仍廣泛流傳於教材與舊代碼。本文依據 C99/C++98/11/14/17/20 標準,徹底釐清 main 正確簽名、返回值語義、return 行為差異與移植性陷阱。
| 標準 | 合法簽名 | 備註 |
|---|---|---|
| C89 | main() / int main() | 隱式 int,已廢棄 |
| C99 | int main(void) | 無參數 |
int main(int argc, char *argv[]) | 命令行參數,argv[0] 為程序名 | |
| C++98/11/14/17/20 | int main() | 等同 int main(void) |
int main(int argc, char *argv[]) | 同 C |
核心鐵律: 返回類型必須是 int,以便向啟動器 (OS/Shell) 傳遞退出碼。void main() **從未** 進入任何標準。
return 0 / EXIT_SUCCESS:正常退出return 非零 / EXIT_FAILURE:異常退出,具體碼可自定義錯誤類型Shell 實驗:
// a.c -> a.exe
int main(void) { return 0; }
Windows CMD:
a.exe echo %ERRORLEVEL% // 顯示 0 a.exe && dir // 返回 0 才執行 dir a.exe || dir // 返回非 0 才執行 dir
Linux Bash:
./a.out echo $? // 顯示 0 ./a.out && echo ok // 同理
main 末尾無 return,編譯器**必須**隱式插入 return 0;建議: 總是顯式寫 return 0;,兼容舊編譯器並明確意圖。
| 場景 | 行為 |
|---|---|
普通函數 return expr; | 彈出棧幀,將 expr 放入返回寄存器 (RAX/EAX),跳回調用點下一條指令 |
main 中 return val; | 啟動器代碼 (__libc_start_main/WinMainCRTStartup) 接收返回值,調用 exit(val) 終止進程 |
main 中無 return (C99+) | 編譯器在生成代碼尾部插入 mov eax, 0; ret |
int main(int argc, char *argv[], char *envp[])第三參數 envp 為環境變量數組,**僅 Linux/Unix 某些編譯器支持**,非標準,**移植性差**,慎用。標準獲取環境變量請用 getenv()。
void: 所有路徑必須 return 值 (C++ 強制,C 警告)void func(): 至少改為 int func() 返回狀態,便於鏈式調用與錯誤處理