楔子: 在華為工作的時候,我常常受邀去給開發團隊做培訓,但其中大多數稱之為座談似乎更恰當些。相對于專業講師不乏調侃的授課方式,我更傾向于直接了當地還原知識的本來面目,少加或者不加個人見解,沒想到居然也贏得了一眾支持者。更為有趣的是,若是所談內容距代碼現場甚遠,則大家更是聽的津津有味,會后我常常被人纏住問個不停,有些問題是他們在工作中遇到的,期望我能給一些提示。可見,在結構化的知識寶庫面前,人的求知欲會強烈地迸發出來,就像孩子面對一朵朵蓬松美麗的棉花糖,已不滿足于僅僅看著了,更渴望把它吃到嘴里細細品味。記得有一次,我在J區華大教室做完《編程之路》的講座,最后一排站起來一位帥哥,他問我怎么才能學好Linux。我建議他不要看那些講內核的書,先認真讀一遍《UNIX環境高級編程》。他比較疑惑,覺得這樣會不會太慢?因為他們的項目要做一些內核的開發工作,而他目前對此還一無所知。我告訴他,快速原型法或許可以短平快地解決某些具體問題,但要真正掌握內核就必須自頂向下地學習,因為操作系統是拿來用的,先理解用戶的需求再考慮怎么實現它,這樣的學習過程才是符合自然規律的。事實上,自然的學習過程適合一切知識,也包括本文及之后系列文章即將詳細介紹的C語言。 C語言是什么? 這是一個非常有意義的問題,也常常被我拿來當成講座的開場白。每到此時,臺下總會有人調皮地說:'C語言就是B語言的兒子。'然后哄堂大笑。不幸的是,即便從最嚴格的意義上看,這個說法也是正確的。大約在1967年,一位叫Martin Richards的英國計算機科學家致力于軟件可移植性的研究,他發明了一種叫做Basic Combined Programming Language的編程語言,也就是計算機專業的學生們所熟知的BCPL。雖然這個語言依舊是無類型(typeless)的,但它引入了一個在當時非常先進的設計--前后端的劃分。前端(front end)解析(Parse)源代碼,生成(Generated)O-code,這是Martin Richards精心設計的偽機器碼,現在稱之為虛擬機代碼或中間描述層(IR)。它帶來的好處是后端僅需做少量的修改就能把O-code進一步轉換(Translated)成真實的目標機器碼。這種設計很快便被其它語言的編譯器所采納并流行至今。 到了1969年,貝爾實驗室一位非常牛逼的始祖級計算機科學家Ken Thompson希望為野心勃勃的Multics工程發明一款輕量級的語言,他精簡了BCPL,然后把這個語言叫做B,意思是去掉了無用的尾巴之后的BCPL。B語言依然是無類型的,但它已經非常接近后來的C語言。譬如,Ken發明了算術賦值運算符,把變量b的值加到變量a可以寫成 a =+ b。在C語言里,寫法是a += b,是不是很相似呢?另外,B語言支持自加(++)和自減(--)運算,用==表示比較運算,用=表示賦值等等。由于是無類型語言,編譯器必須知道何時執行數值運算,何時執行地址運算。B語言用唯一的類型--計算機字和運算符的組合解決了這個問題。當操作數(變量)被用于諸如四則運算時,它就是整數,否則是地址。有了地址就必須解引用,這就是C語言指針的雛形。 B語言在當時的DEC PDP-7上工作良好,但隨著PDP-11的誕生,無類型的B語言不能優雅地處理字節數據類型(它的內部運算都是integer),而這恰恰是新的計算機硬件最突出的特性。貝爾實驗室的另一位大佬,也是Ken Thompson的好基友Dennis Ritchie終于無法忍受,他迫切需要一種更為強大的語言以便把UNIX移植從PDP-7上面移植過來。大師的牛逼之處就在于此,他既沒有去網上發帖抱怨,也沒有去找風投說概念拉團隊。而是自己動手,對B語言做了深入的優化,添加了豐富的數據類型并用它重寫了UNIX,一款改變計算機歷史的語言就這么誕生了。直到1971年,Ritchie仍然稱這個語言為'New B'簡寫為'NB'(大師也知道自己的牛逼之處啊)。隨著新語言的不斷被改進,類型系統越來越豐富,例如可以寫這樣復雜的聲明:int *api[10], (*pai)[10]; Ritchie覺得是時候自立門戶了,于是,在1972年,大師說:'I felt that it deserved a new name; NB seemed insufficiently distinctive. I decided to follow the single-letter style and called it C'。 從此,C語言就開始了長達四十年的統治地位。 |
|