Try   HackMD

C 語言演化背景和編譯器原理

tags: sysprog

主講人: jserv / 課程討論區: 2017 年系統軟體課程

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
返回「嵌入式作業系統設計與實作」課程進度表

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

  • 25 年之間的變化 [ source ]

C 語言的演化

像英文一樣,C 是種進化的語言。語言的變化可能是好的,字彙的擴充可容納新的觀念與需求。但若不能加以約束,而任由使用者恣意變更,則可能導致問題叢生,引發不能相容的「方言」。從 1987 年開始,C 標準的定義就一直沿用《The C Programming Language》(Kernighan & Ritchie) 書本的 reference 一節。C 語言最初使用於 UNIX 作業系統環境,之後則廣泛使用於 Apple DOS, MS-DOS 等環境中,軟體開發商對於跨平台的需求越來越高,於是 C 語言標準制定因應而生。

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

  • Jonathan Adamczewski 貼出經典著作《The C Programming Language》,然後評註說:

  • "C++: The Good Parts"

早期的 C 語言

最早的 C 語言編譯器由 Dennis Ritchie 開發,使用 recursive descent parser, 並輸出 PDP-11 機械碼。而之後許多編譯器引入 yacc 來產生 parser,也因此,yacc 稱為 compiler-compiler。

Recursive descent parser 為什麼是這樣的名稱呢?

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

看過上圖,就不難理解,採用遞迴去實做的語法解析器,稱為 Recursive descent parserRecursive descent parser 很好實作 (就是程式很好寫),難的是什麼?如何將語法規則寫出來,並且還要需要符合 LL(1)。LL 分析器是自頂向下用的一個分析方法,所以 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 ]
    • 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)]).

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

為什麼你該理解編譯器的原理

編譯器和最佳化原理