不知道你們有沒有想過一個問題:C語言編譯器爲何可以用C語言編寫?python
所謂C語言編譯器,就是把編程獲得的文件,好比.c,.h的文件,進行讀取,並對內容進行分析,按照C語言的規則,將其轉換成cpu能夠執行的二進制文件。程序員
其本質在於對文件的讀入,分析,及處理。這些操做,C語言都是能夠實現的。編程
因此用C語言來作C語言的編譯器是徹底可行的。編程語言
可是,歷史上的第一個C語言編譯器,確定不是C語言寫的,由於在沒有編譯器時,沒法把C語言轉換成可執行文件。只要有了初版其它語言的編譯器,就能夠用C語言寫編譯器了。學習
那麼世界上第一個C語言編譯器又是怎麼編寫的呢?操作系統
仍是讓咱們回顧一下C語言歷史:設計
1970年Tomphson和Ritchie在BCPL(一種解釋型語言)的基礎上開發了B語言,3d
1973年又在B語言的基礎上成功開發出瞭如今的C語言。orm
在C語言被用做系統編程語言以前,Tomphson已經使用B語言編寫過操做系統。可見在C語言實現之前,B語言已經能夠投使用了。開發
所以第一個C語言編譯器的原型徹底多是用B語言或者混合B語言與PDP彙編語言編寫的。
事實上,B語言的執行效率比較低,可是若是所有用匯編語言來編寫,不只工做量巨大,並且彙編語言的可讀性極差,很容易就會出錯!
上一張圖你們感覺一下這巨大的差異!!!
爲了克服這個困難,早期的C語言編譯器就採起了一個取巧的辦法:先用匯編語言編寫一個C語言的一個子集的編譯器,再經過這個子集去遞推完成完整的C語言編譯器。
大體過程以下:
先創造一個只有C語言最基本功能的子集,記做C0語言,C0語言已經足夠簡單了,能夠直接用匯編語言編寫出C0的編譯器。
依靠C0已有的功能,設計比C0複雜,但仍然不完整的C語言的又一個子集C1語言,其中C0屬於C1,C1屬於C,用C0開發出C1語言的編譯器。
在C1的基礎上設計C語言的又一個子集C2語言,C2語言比C1複雜,可是仍然不是完整的C語言,開發出C2語言的編譯器……如此直到CN,CN已經足夠強大了,這時候就足夠開發出完整的C語言編譯器的實現了。
至於這裏的N是多少,這取決於你的目標語言(這裏是C語言)的複雜程度和程序員的編程能力。
那麼這種大膽的子集簡化的方法,又有什麼理論依據呢?
先介紹一個概念,「自編譯」Self-Compile。
對於某些具備明顯自舉(不知道哪一個鬼才起的名字)性質的強類型編程語言
能夠藉助它們的一個有限小子集
經過有限次數的遞推來實現對它們自身的表述
(所謂強類型就是程序中的每一個變量必須聲明類型後才能使用,好比C語言,相反有些腳本語言則根本沒有類型這一說法,好比python。)
知足自編譯這樣的語言有C、Pascal、Ada等等,至於爲何能夠自編譯,能夠參見清華大學出版社的《編譯原理》,書中實現了一個Pascal的子集的編譯器。
總之,已經有計算機科學家證實了,C語言理論上是能夠經過上面的方法實現完整的編譯器的。