隨著人工智慧的爆紅,全民學程式設計似乎已經成為一種風尚,各種Java、PHP、Ruby或Python語言的培訓課程如雨後春筍般湧現。
不過,對於真正科班出身的程式設計師或理工科背景的人來講,學生時代印象最深刻的程式語言應該還是非C語言莫屬。
事實上,C語言影響了自20世紀80年代以來開發的幾乎所有程式語言。一些語言如C++、C#和objective C語言成為了該語言的直接繼承者,而其他語言也不過是採用和改編了C的語法。
我們甚至可以說,C語言幾乎就是程式設計師之間的通用語言。
但是,C語言並不是完全憑空出現的,它的故事還要從一個“跳棋”小遊戲講起。
“能夠寫出完美程式的人”二戰後,戰爭期間延續下來的密碼學和計算機技術催生出了“程式設計師”這一新的社會角色。
在英國,就有一位被稱為“能夠寫出完美程式的人”——克里斯托弗·斯特雷奇(Christopher Strachey)。
斯特雷奇於1916年出生在英國的一個的名門望族,他的叔叔萊頓·斯特雷奇(Lytton Strachey)是二戰期間文人團體布盧姆茨伯裡派(Bloomsbury Group)的創始人之一,而他的父親奧利弗·斯特雷奇(Oliver Strachey)則在兩次世界大戰期間都對盟軍的密碼破譯活動起到了重要作用。
克里斯托弗·斯特雷奇
虎父無犬子,斯特雷奇自己最終也成為公認的程式設計和計算機科學專家。
在二戰期間,斯特雷奇為英國一家電子公司工作,之後成為一名教師,最終落戶於倫敦最負盛名的公立學校哈羅公學(Harrow)。
1951年,斯特雷奇經人介紹認識了英國國家物理實驗室的邁克·伍德格(Mike Woodger),這是他第一次接觸到計算機。
在用一天的時間熟悉了實驗室的Pilot ACE計算機之後,他回到哈羅公學,用空閒時間鑽研如何教計算機下跳棋。
第一次的努力並沒有取得成果,Pilot ACE根本沒有玩跳棋所需的儲存容量。當時計算機的價值主要在於它們快速解方程的能力,但斯特雷奇對它們執行邏輯任務的能力更感興趣。
那年春末,他發現了曼徹斯特大學有費蘭蒂馬克一型(Ferranti Mark I)計算機,而鼎鼎大名的艾倫·圖靈(Alan Turing)恰好是該校計算機實驗室的助理主任。
圖靈曾寫過程式設計師手冊,斯特雷奇與圖靈在劍橋大學時就很熟,於是向他要了一份手冊。
模擬器可以讓程式設計師一步步看到計算機如何執行程式。這樣的“跟蹤”程式將突出程式造成瓶頸或執行效率低下的地方。在那個計算機記憶體和處理器週期都很昂貴的時代,這是程式設計的一個重要方面。
當時,斯特雷奇編寫的跟蹤程式有一千多條指令,它是為Ferranti Mark I編寫過的最長的程式。
克里斯托弗·斯特雷奇與Ferranti Mark I計算機
很快,斯特雷奇引起了英國國家研究與發展公司總經理哈斯伯裡勳爵(Lord Halsbury)的注意,他很快就聘請斯特雷奇,以推動英國大學計算機科學快速發展的實際應用。
正是在這個職位上,他發現了劍橋大學正在進行的一個專案,該專案由一個名叫大衛(David)的程式設計師三人組負責。
三人分別為大衛·哈特利(David Hartley)、大衛·惠勒(David Wheeler)和大衛·巴倫(David Barron),正是這三人參與了C語言的早期開發。
新語言五人組劍橋大學的計算中心有很強的服務意識。數學實驗室的第一臺計算機EDSAC和EDSAC 2提供給大學其他地方的研究人員使用,他們編寫的程式被列印在紙帶上,然後輸入機器。
在計算中心,這些紙帶被夾在晾衣繩上,在工作時間內一個接一個地執行。這一排排待處理的程式被稱為“作業佇列”,這個術語至今仍被用來描述更復雜的組織計算任務的方法。
在EDSAC 2上線僅兩年後,劍橋大學就意識到,很快就需要一臺功能更強大的機器,為了實現這一目標,他們需要購買一臺商用主機。劍橋大學同時考慮了IBM 7090和Ferranti Atlas,但發現都買不起。
1961年,Ferranti公司的部門經理彼得·霍爾(Peter Hall)建議他們可以與劍橋大學聯合開發Atlas計算機的簡化版。劍橋大學將得到這臺名為“泰坦”(Titan)的原型機,而Ferranti公司則可以將新計算機推銷給那些買不起Atlas系統的客戶。
為了向大學的其他學生提供計算服務,這臺新計算機既需要一個作業系統,也需要至少一種高階程式語言。
但當時幾乎沒人考慮過要擴充套件為EDSAC 2開發的語言。“在20世紀60年代早期,人們普遍認為,‘我們正在建造一臺新的計算機,所以我們需要一種新的程式語言’。”大衛·哈特利在2017年的一次播客中回憶道。
“開發新的作業系統是必需的,”據哈特利說,但新的程式語言卻不是。“我們起初只是帶著玩一玩的心態開發新語言,沒想到事後證明竟是一件蠢事。”
負責監督Titan專案的莫里斯·威爾克斯(Maurice Wilkes)也認為,沒有必要使用新的程式語言。
Titan的主要理由是為劍橋大學的其他學生提供計算服務,為此,最好的辦法是讓機器儘快啟動和執行,並配備使用者已經熟悉的語言。
在批准開發新語言的提案之前,威爾克斯要求對現有的程式語言進行分析。
最終,在1962年6月,三人組準備了一篇論文,認為有必要開發一種新的語言。
這種新的程式語言被稱為CPL(劍橋程式語言),到1963年,工作已經順利展開。
來自倫敦大學的約翰·巴克斯頓(John Buxton)和埃裡克·尼克松(Eric Nixon)加入了劍橋程式設計師的行列。
隨著專案的發展,威爾克斯決定請本文主角斯特雷奇來監督這個專案。這群研究新語言的人會在劍橋或倫敦開會。
那時,大衛·惠勒已經轉戰其他專案,留下了一個五人團隊:哈特利、巴倫、布克斯頓、尼克松和斯特雷奇。
這群人一開始就制定了ALGOL 60的規範,目標是寫出一種“完美”的語言——一種既適用於各種使用者,又美觀、高效的語言。
但很快,他們就遇到了一些困難,有一個小爭議是斯特雷奇反對“IF......THEN......ELSE”語句的語法。他更喜歡“OR”,但這與幾乎所有其他程式語言中使用“OR”的方式相沖突。
儘管如此,他的喜好還是延續了下來,CPL參考手冊在使用者本以為是“ELSE”的地方加入了 “OR”。
另外,團隊還投入了寶貴的時間來開發一種避免使用星號(*)來表示乘法的方法。在這裡,美學上的考慮導致問題變得複雜,延遲了程式語言的實現,因為必須制定複雜的規則來區分“3a”(意思是“3*a”)和“3a”(作為變數名)。
與此同時,劍橋大學的使用者對該校新的Atlas計算機缺乏可用的程式語言越來越感到沮喪。該語言的規格基本完成,但沒有可用的編譯器。工作組把CPL搞得非常複雜,以至於早期編寫編譯器的嘗試導致機器程式碼的效率非常低。
從“B”到“C”1965年,斯特雷奇前往麻省理工學院呆了幾個月,回來後,他擔任了牛津大學程式設計研究組的主任。與此同時,馬丁·理查茲(Martin Richards)也加入了CPL專案。他開始著手開發一個可以提供給使用者的有限版本的CPL——BCPL。
在麻省理工學院期間,斯特雷奇幫助馬丁·理查茲安排了兩年的學術休假,1966年,理查茲帶著BCPL來到了馬薩諸塞州,在那裡,他得以繼續BCPL編譯器的開發工作。
BCPL是一種“自舉法”(Bootstrapping)語言,因為它的編譯器能夠自我編譯。基本上,BCPL編譯器的一小塊是用匯編或機器程式碼編寫的,編譯器的其餘部分將用BCPL的相應子集編寫。
用BCPL編寫的編譯器部分將被輸入到用匯編程式碼編寫的部分,由此產生的編譯器程式可以用來編譯任何用BCPL編寫的程式。
“自舉法”編譯器極大地簡化了將語言從一臺計算機或作業系統移植到另一臺計算機或作業系統的過程。只需要在編譯器中寫的相對較小的特有程式碼,就可以使編譯器能夠在另一臺計算機上執行。
當理查茲在麻省理工學院研究BCPL編譯器時,MIT正與貝爾實驗室和GE公司一起參與Multics專案。為了支援這個專案,麻省理工學院和貝爾實驗室建立了一個網路。
貝爾實驗室
儘管兩地之間的網路連線名義上是為了促進Multics的工作,但在MIT的主機上“徘徊”檢視其他專案也是被接受的,肯·湯普森(Ken Thompson)就是這樣找到BCPL的程式碼和文件的。他把它下載到貝爾實驗室的一臺主機上,開始使用它。
大約在湯普森進行 BCPL 實驗的時候,貝爾實驗室退出了Multics聯盟,湯普森工作的計算機科學部門暫時沒有任何型別的計算機。
最終,他們獲得了一臺手工製作的Digital PDP-7計算機,即使以那個時代的標準來看,也不是特別強大。儘管如此,湯普森還是在那臺機器上啟動並運行了第一個版本的Unix。
PDP-7 有 8,192 個“字”的記憶體(在這個例子中,一個字是 18 位,當時業界還沒有標準化的 8 位“位元組”)。Unix 佔用了前 4k,留下 4k 空閒的空間來執行程式。
湯普森把他的BCPL副本進一步壓縮,使它能適應PDP-7上可用的4k記憶體。
在這個過程中,他借用了他在加州大學伯克利分校學習時遇到的一種語言。那個語言“SMALGOL”是ALGOL 60的一個子集,旨在執行在功能較弱的計算機上。
湯普森最終在PDP-7上使用的語言是“BCPL語義與大量的SMALGOL語法的結合體”,這意味著它看起來像SMALGOL,工作起來像BCPL。
由於這種新語言只包含了BCPL中湯普森認為最有用的方面,而且可以裝進相當狹窄的PDP-7中,所以他決定將“BCPL”這個名字縮短為“B”。
此前,湯普森曾用匯編器為PDP-7編寫了Unix,但即使在1969年,這也不是編寫作業系統的理想方式。它對PDP-7有用,因為那臺計算機相當簡單,而且湯普森編寫作業系統主要是為了自娛自樂。
任何一個作業系統,如果要由多個程式設計師維護和更新,並能在當時比較複雜的硬體上執行,就需要用高階程式語言來編寫。
因此,當貝爾實驗室在1971年為該部門購買了一臺PDP-11時,湯普森決定用高階程式語言重寫Unix。
與此同時,丹尼斯·裡奇(Dennis Ritchie)已經採用了B語言,並將其改編為在更強大的計算機上執行。
他首先在B語言中新增的第一個東西是“輸入”變數的能力。因為PDP-7的記憶體是由18位字組成的,所以B語言可以透過將每個變數看作是一個單一的記憶體字,或者是一個連續的字,透過它們在系統記憶體中的位置進行引用來簡化。
這樣的方法在記憶體很小、使用者基數很小的簡單機器上是有效的,但在更復雜的系統上,程式更復雜,使用者更多,這可能導致確定一個變數是字串還是數字需要特殊手段,同時造成記憶體使用效率低下。
裡奇將這種修改後的語言命名為“New B”,縮寫為NB(呃,誤打誤撞的諧音梗!)。它被安裝在Murray Hill計算中心的主機上,這使得整個貝爾實驗室的使用者都可以使用它。
自然,當湯普森決定用高階語言重寫Unix時,他從NB開始,可惜他的前三次嘗試都以失敗告終。
每次出現故障,裡奇都會以一種對他和湯普森來說有意義的方式為 NB 新增功能,而且一旦他添加了結構,湯普森就能夠用這種新語言編寫 Unix。
於是,裡奇和湯普森認為結構體的加入是一個重大的變化,有足夠的理由為程式語言重新命名,於是B語言變成了C語言。
走向世界隨著商業化條件的成熟,C語言和Unix開始走出貝爾實驗室。
在這過程中,PDP-11迅速成為市場上最成功的微型計算機之一對C語言和Unix的推廣功不可沒。
任何擁有PDP-11的計算中心都可以在上面安裝Unix,而Unix的低成本使它對大學特別有吸引力。於是,C與Unix一起出現在大學生面前。
1978年,裡奇和布萊恩·柯林漢(Brian Kernighan)出版的《C程式語言》進一步推動了C語言的成功。即使在當時,這本228頁的薄書也是一本非常簡單易懂的著作。
C語言語法的廣泛傳播影響了許多後續語言的發展。不過,湯普森從都不相信C語言會像現在這樣普及,“我的美學意識告訴我,一種語言不可能覆蓋整個宇宙。”湯普森說。
和Unix一樣,C語言也是在失敗中誕生的成功產物。Multics 催生了 Unix,在其鼎盛時期,全球只在約80臺計算機使用。而最終產生了C語言的CPL在1967年還沒完成就被劍橋大學的研究人員放棄了。
當斯特雷奇在牛津大學成立程式設計研究小組時,他說:“把實際工作和理論工作分開是人為的,是有害的。”而CPL的本意是將實踐和理論的關注點結合起來。
正如湯普森回憶道,“C語言是為了Unix而寫的,而Unix是為了讓我們所有人都能寫程式而寫的。”
參考資料:https://arstechnica.com/features/2020/12/a-damn-stupid-thing-to-do-the-origins-of-c/