當前位置: 華文問答 > 數碼

C 語言的「void main」是怎麽一代代傳下來的?

2020-01-20數碼

這個問題下許多人都是答非所問或者帶著惡意亂猜的,從微軟到NeXT的官方文件裏,大概從1988年開始大量的資料裏的C程式碼都有出現void main() 或者 void main(void)的寫法,幾乎成了一種 工程上的約定俗成 ,這真的就沒有意義嗎?還有甩鍋給譚C的,更是無稽之談,難道微軟和Borland的工程師也是跟譚C學的?

NeXTSTEP文件中的void main

在搞明白void main的來歷之前,我們必須要先搞明白在(C89之前的)早期的C語言實作中,void關鍵字以及void作為返回的函數,比如void somefunc()是怎麽來的,定義是什麽,使用的場景是什麽,再去考慮使用以void作為返回的主函數,也就是void main()的原因。C89標準翻遍也未必給你答案,因為在電腦編程這樣的領域, 工程實踐是早於行業標準的,編譯器的實作就是使用者的標準。

1989年一份介紹Microsoft Quick C升級的介紹裏,螢幕上的截圖寫道

Returns : a pointer to void if successful , or NULL if not .

這段說明很顯然是來自Quick C的某個幫助文件的,成功就返回void的指標,失敗則返回空。雖然不是用void做main的返回值,但我們看到void作為返回值確實有其套用場景的。

我們再往前追,1988年9月份的PC Magazine,看到了void main的寫法,不得不說那個時代的電腦雜誌真硬核,各種程式碼

不知不覺間我們已經逼近void指標發明的時候了,在The Art of UNIX Programming一書中層介紹到void指標起源於將C標準化的努力

在C++的發明者Bjarne Stroustrup的文章Sibling Rivalry: C and C++中,提到了「古典C語言」的概念,Steve Johnson(yacc的發明人)開發的PCC(Portable C Compiler)添加了void,列舉類別和struct,它們在ANSI標準之前被廣泛使用。

然後再往後看,我們就看到了大量以void開頭的函數

這樣看來,C語言中使用void作為返回值或許是受到C++的前身C with classes的影響,而理由則是類別安全

Whatever the origin, what was implemented in C with classes was a simple type-safe notion of memory holding objects of unknown type. Any pointer can be implicitly converted to void*, and any use of the memory referred to by a void* involves a cast to some type.
無論起源如何,在C with classes中實作的都是一個簡單的類別安全的概念,用於儲存未知類別的物件。任何指標都可以隱式轉換為void *,並且對void *所參照的記憶體的任何使用都涉及到將其轉換為某種類別。

但是我們還是不清楚void main的最初起源是哪裏,它出現在RSA的md5程式碼裏,出現在NASA的文件裏,出現在史丹佛線性加速實驗室的論文裏,出現在惠普開發的早期的motif程式碼裏,出現在SAS C編譯器的手冊裏,它出現的平台跨越了DOS、Unix、Commodore 64、Amiga OS乃至Cray超級電腦,它註定是某種「事實標準」而不是個別工程師的錯誤

1990年RSA的MD5實作:https:// people.csail.mit.edu/ri vest/Md5.c

1988年NASA的並列矩陣乘法程式碼:https:// ntrs.nasa.gov/archive/n asa/casi.ntrs.nasa.gov/19890017256.pdf

1990年史丹佛線性加速實驗室的論文:https://www. slac.stanford.edu/cgi-b in/getdoc/slac-pub-5251.pdf

1990年惠普實驗室的期刊 https://www. hpl.hp.com/hpjournal/pd fs/IssuePDFs/1990-06.pdf

1996年,SAS C編譯器手冊 https:// support.sas.com/documen tation/onlinedoc/sasc/doc650/clug.pdf

我目前能找到的最早的帶有void main的手冊是1985年一系列MetaWare High C編譯器的手冊,在High C Programmer's Guide和High C Library Reference Manual裏都出現了帶有void main的例子。

而更多的例子,出現在Lattice AmigaDOS C Compiler手冊裏,Lattice C Compiler是非常著名的微處理器C編譯器,早期的Microsoft C Compiler就是從它貼牌而來,而對於Amiga平台來說Lattice C Compiler則是預設的C編譯器。

上面的截圖中「Returns」(返回)一節提到,「If you want to pass a non-zero termination code back to AmigaDOS, use the exit or _exit function」,非零的返回值不能直接由main函數返回,而需要呼叫額外的函數。這或許就是當時沒有用int main的理由。

在1988年的Turbo C Reference Guide中,我們同樣看到void main的出現,由於Turbo C在IBM PC開發者之間非常流行,最終void main成為了「事實標準」。