跳轉到

1972:C 語言 — 在 BCPL 的灰燼上鑄出的系統之劍#

案情#

1972 年初,貝爾實驥室的 Dennis Ritchie 在新澤西州 Murray Hill 的 PDP-11 上完成了 C 語言的初期實作。這門語言承繼 CPL→BCPL→B 的血統,但加入了資料型別、字元處理與編譯效率的改良。到 1973 年夏天,Thompson 與 Ritchie 用 C 成功重寫了 UNIX 核心,作業系統史上第一次,「高階語言寫的系統核心」跑出了不輸組合語言的效能。

前因#

  • 1960 年代的 CPL(Cambridge + London)野心過大,從未實用。
  • Martin Richards 的 BCPL(1967)砍到只剩一種型別——機器字組,極簡但缺乏字元與浮點支援。
  • Thompson 在 PDP-7 上基於 BCPL 改造出 B 語言(1969–70),仍是無型別、字組定址。
  • PDP-11 到貨:有字元(byte)定址、硬體浮點選配,B 語言格格不入——這正是案發現場的「凶器不符」。

線索與推理#

偵探問:為什麼 C 會在此時此地出現?線索指向硬體。B 語言把一切當成一個機器字組,在字組定址的 PDP-7 上合理;但 PDP-11 是 byte 定址機器,處理文字、字串成了痛點。Ritchie 的破案關鍵是「型別再引入」:他沒有回到 Fortran 式的繁瑣,而是設計出一套精巧的型別系統——基本型別(char、int、float、double)加上「以指標與陣列推導型別」的遞迴規則:

\[ T \; ; \; \text{若 } x \text{ 為型別 } T \text{,則 } *x \text{ 為 } T \text{,} x[n] \text{ 為 } T \text{ 的陣列} \]

這讓 C 既能描述位元組、字組、浮點,又能用同一套語法操作位址——指標運算 p + 1 的意義由所指型別的大小決定(sizeof(T)),編譯器自動乘上偏移。這是優雅的抽象:語言把「位址算術」變成了型別系統的內建功能。

第二問:為何敢用 C 重寫 UNIX?Thompson 先在 1972 年做局部實驗(I/O 子系統),證實編譯器產生的碼夠快;1973 年完成核心整體重寫。決策邏輯是工程師式的:先用最小實驗驗證風險,再全面賭注。結果是 UNIX 獲得可攜性——1976-77 年搬到 Interdata 8/32 只花數月,組合語言版本的 UNIX 永遠做不到。

理論#

C 的血統表:

年代 語言 作者 特徵
1963 CPL Cambridge/London 龐大,未實用
1967 BCPL M. Richards 無型別,僅機器字組
1970 B K. Thompson 無型別,直譯+執行緒模型簡化
1972 C D. Ritchie 型別化、編譯式、貼近硬體

C 的設計核心可濃縮為一句:信任程式設計師。沒有邊界檢查、沒有垃圾回收,指標就是位址。範例片段(1978 年 K&R 風格):

char *strcpy(s, t)   /* 把 t 複製到 s */
char *s, *t;
{
    char *p = s;
    while (*p++ = *t++)
        ;
    return s;
}

四行做完字串拷貝——簡潔的代價是所有指標錯誤都由程式設計師自負。K&R(Kernighan & Ritchie)1978 年出版的《The C Programming Language》成為史上印行量最大的技術書之一。

後果#

  • 1977-79 年 UNIX/32V 與 4BSD 的可攜化,UNIX 隨 VAX 席捲學術界。
  • 1983 年 ANSI 成立 X3J11 委員會,1989 年公布 ANSI C 標準。
  • C 幾乎成為所有後續語言的基底:C++、Objective-C、Java、C#、Go、JavaScript 的語法皆受其影響;作業系統核心(Linux、Windows 大部、macOS/XNU)至今以 C 為主。
  • Ritchie 與 Thompson 獲 1983 年圖靈獎。

冷案檔案#

  • 時間:1972 年(PDP-11 初版);1973 年 UNIX 核心重寫完成
  • 案由:新硬體(byte 定址)迫使語言演化,型別系統與指標的再發明
  • 歷史定位:C 是「系統程式設計的拉丁文」——五十年後仍被整個數位世界每天執行。