# C 語言演化背景和編譯器原理 ###### tags: `sysprog` :::info 主講人: [jserv](http://wiki.csie.ncku.edu.tw/User/jserv) / 課程討論區: [2017 年系統軟體課程](https://www.facebook.com/groups/system.software2017/) :mega: 返回「[嵌入式作業系統設計與實作](http://wiki.csie.ncku.edu.tw/sysprog/schedule)」課程進度表 ::: ![](https://hackpad-attachments.s3.amazonaws.com/embedded2016.hackpad.com_r9qLWYxk2Yf_p.537916_1460307402053_undefined) * 25 年之間的變化 [ [source](https://twitter.com/historyinmoment/status/719193743245516801/photo/1) ] ## C 語言的演化 像英文一樣,C 是種進化的語言。語言的變化可能是好的,字彙的擴充可容納新的觀念與需求。但若不能加以約束,而任由使用者恣意變更,則可能導致問題叢生,引發不能相容的「方言」。從 1987 年開始,C 標準的定義就一直沿用《[The C Programming Language](https://en.wikipedia.org/wiki/The_C_Programming_Language)》(Kernighan & Ritchie) 書本的 reference 一節。C 語言最初使用於 UNIX 作業系統環境,之後則廣泛使用於 Apple DOS, MS-DOS 等環境中,軟體開發商對於跨平台的需求越來越高,於是 C 語言標準制定因應而生。 ![](https://hackpad-attachments.s3.amazonaws.com/embedded2015.hackpad.com_s0rlzR8wVtm_p.299401_1448123032402_book.jpg) * [Jonathan Adamczewski](https://twitter.com/twoscomplement) 貼出經典著作《The C Programming Language》,然後評註說: * "**C++: The Good Parts**" **早期的 C 語言** * [Very early C compilers and language](https://www.bell-labs.com/usr/dmr/www/primevalC.html) * [cc / unix-v1](https://github.com/jserv/unix-v1/tree/master/src/c) * [以工程觀點重新檢視 UNIX 與 C 語言](http://www.slideshare.net/jserv/unix-crevise) * [UNIX Internals](http://www.slideshare.net/jserv/unix-v6study) (Page 54-58) 最早的 C 語言編譯器由 [Dennis Ritchie](https://en.wikipedia.org/wiki/Dennis_Ritchie) 開發,使用 [recursive descent parser](https://en.wikipedia.org/wiki/Recursive_descent_parser), 並輸出 [PDP-11](https://en.wikipedia.org/wiki/PDP-11) 機械碼。而之後許多編譯器引入 yacc 來產生 parser,也因此,yacc 稱為 compiler-compiler。  [Recursive descent parser](https://en.wikipedia.org/wiki/Recursive_descent_parser) 為什麼是這樣的名稱呢? ![](https://hackpad-attachments.s3.amazonaws.com/fossapc.hackpad.com_W4DY7Fi7YbG_p.131666_1460398373580_scc.png) 看過上圖,就不難理解,採用遞迴去實做的語法解析器,稱為 [Recursive descent parser](https://en.wikipedia.org/wiki/Recursive_descent_parser)。[Recursive descent parser](https://en.wikipedia.org/wiki/Recursive_descent_parser) 很好實作 (就是程式很好寫),難的是什麼?如何將語法規則寫出來,並且還要需要符合 LL(1)。LL 分析器是自頂向下用的一個分析方法,所以 [Recursive descent parser](https://en.wikipedia.org/wiki/Recursive_descent_parser) 可用,但文法規則要符合 LL(1)。因此,倘若你的文法規則不符合 LL(1),就需要改寫規則,使其符合 LL(1)。 那什麼是 LL(1)?就是在解析文法時,要多讀一個 token 來判斷,多讀兩個來判度就是 LL(2),以此類推。 1983 年起,ANSI (美國國家標準協會) 著手制定 C 語言標準,於是有了 C89,這在 1989 年定案。相較於 K&R C 的變革: * portability : signed/unsigned, short int * const, volatile, enum, long double * 浮點數支援 * 允許 struct 當作函式參數來傳遞 * void : `(void) printf("Black Hole\n");` * C 標準函式庫,獨立於作業系統 **C 標準函式庫** K&R C 原本的參考定義中,並不包含任何函式庫,甚至連輸入、輸出函式都由編譯器的設計者自行斟酌處理。不過在 K&R 的書中,的確討論到幾個為 UNIX 環境發展的「標準」,其中有些函式像是 open() 和 write(),直接併入 UNIX 作業系統,稱為系統呼叫 (system call),而像是 printf(), fopen(), getchar() 則為了方便使用而開發,隨後納入 UNIX C Library。值得注意的是,getchar() 實際上是定義為 macro,但系統也提供可呼叫的函式。 一般來說,編譯器設計者可建立自己的函式庫,但大多力求接近 UNIX 模型,再來補充個別系統的特色。比方說,IBM DOS 環境需要用到中斷處理 (interrupt),於是編譯器供應商則提供足以開發中斷處理常式 (ISR) 的函式。 過去開發者抱怨 C 執行浮點數運算不快,這是因為浮點數運算的自動提昇 (auto-promotion)。在 ANSI C 標準中,只要接受運算結果的對象和運算元類型相同,就可省略轉換為 double 的過程。 **C++** C++ 由 Bell Labs 的 Bjarne Stroustrup 發展,於 1983 年問世,恰好就在 C 語言標準著手制定之際。C++ 的一些特徵,像是 const 關鍵字和 function prototype,被 ANSI C 所採納。從 C 語言演化到 C++ 之前,後者稱為 "C with classes" * [ [source](https://twitter.com/RichRogersHDS/status/666798359244611584) ] * In Ruby, everything is an object. * In Clojure, everything is a list. * In Javascript, everything is a terrible mistake. * in C, everything is a representation (unsigned char [sizeof(TYPE)]). ![](https://hackpad-attachments.s3.amazonaws.com/embedded2015.hackpad.com_s0rlzR8wVtm_p.299401_1448056876595_timeline.png) * [ [source](https://isocpp.org/std/status) ] ## 為什麼你該理解編譯器的原理 * 其中一個理由是理解編譯器的限制: [gcc can’t handle too much ](http://peter.kingofcoders.com/?p=1799)[#if](https://embedded2015.hackpad.com/ep/search/?q=%23if&via=DWAUb7NnQF0)[ macro](http://peter.kingofcoders.com/?p=1799) * [Compiler 的多元應用](https://embedded2015.hackpad.com/Compiler-rtfoECtyuOd) * [What Can Compilers Do for Us?](http://www.slideshare.net/jserv/what-can-compilers-do-for-us) * 電腦科學最早的思想體系 ## 編譯器和最佳化原理 * 詳情參閱: [共筆](https://hackmd.io/s/Hy72937Me)