索引 / 001 ZH-TW
C程式設計語言 cover

電腦科學

電腦科學

C程式設計語言

Brian W. Kernighan; Dennis M. Ritchie

英文原名: The C Programming Language

簡潔經典的 C 語言入門書,透過函式、型別、指標、記憶體和可攜式系統程式碼講解程式設計基礎。

難度等級
中級
學術層次
大學部
C語言程式語言指標記憶體演算法系統程式設計

01 / 導讀

導讀

引用

Kernighan, B. W., & Ritchie, D. M. (1988). The C Programming Language (2nd ed.). Prentice Hall.

章節概要

第二版篇幅緊湊(出版社列出的頁數為288頁,索引從第263頁開始),包括序言、導言、八章和三個附錄。本書由 C 語言的設計者 Ritchie 和他在貝爾實驗室的同事合著,按照 ANSI 標準描述 C 語言——本書付印時該標準正在定稿;最早的印次封面上印有「Based on Draft-Proposed ANSI C」,之後的印次則印有紅色的「ANSI C」字樣。序言說明了作者的目標:保持第一版(1978年)的簡潔,因為 C 不是一門大語言,也不適合用一本大書來講;改進對指標等核心特性的講解;主要透過閱讀、編寫和修改完整且經過測試的程式來教學,而不是羅列規則。各章都有編號的練習。

第1章:A Tutorial Introduction(入門教學)

快速瀏覽語言的核心部分,目的是讓讀者儘快開始寫程式:入門、變數與算術表示式、for 語句、符號常量、字元輸入與輸出、陣列、函式、傳值呼叫、字元陣列,以及外部變數與作用域。導言明確指出,這一教學假定讀者具備程式設計的實際知識,不解釋電腦、編譯或賦值語句的含義。

第2章:Types, Operators, and Expressions(型別、運算子與表示式)

更正式的講解從這裡開始:變數名、資料型別與長度、常量、宣告、算術運算子、關係與邏輯運算子、型別轉換、自增與自減運算子、按位運算子、賦值運算子、條件表示式,以及優先順序與求值次序。

第3章:Control Flow(控制流)

語句與區塊、if-else 和 else-if 結構、switch、while 和 for 迴圈、do-while、break 和 continue,以及 goto 與標籤。出版社公開的本章樣章體現了全書的風格:簡短而完整的函式(二分查詢、數字與字串之間的轉換),後面是要求讀者改寫或擴展這些函式的練習。

第4章:Functions and Program Structure(函式與程式結構)

函式以及如何圍繞函式組織程式:返回非整數值的函式、外部變數、作用域規則、標頭檔、靜態變數和暫存器變數、區塊結構、初始化、遞迴,以及 C 前處理器。據導言介紹,本章也討論分佈在多個原始檔中的程式。

第5章:Pointers and Arrays(指標與陣列)

這是講解語言的各章中最長的一章,也是序言特別提到改進了講解的一章。內容包括指標與地址、作為函式參數的指標、指標與陣列的關係、地址運算、字元指標、指標陣列與指向指標的指標、多維陣列、命令列參數、指向函式的指標,以及複雜宣告;據序言介紹,最後這部分用把宣告轉換為文字、再把文字轉換回宣告的程式來說明。

第6章:Structures(結構)

結構及其與函式的配合、結構陣列、指向結構的指標、自我參照結構(鏈結資料結構的基礎)、一個表查詢的例子、typedef、聯合以及位欄位。

第7章:Input and Output(輸入與輸出)

把標準函式庫作為通向作業系統的可移植介面:標準輸入與輸出、用 printf 進行格式化輸出、變長參數列、用 scanf 進行格式化輸入、檔案存取、用 stderr 和 exit 處理錯誤、行輸入與輸出,以及其他函式。

第8章:The UNIX System Interface(UNIX 系統介面)

C 程式如何直接使用 UNIX 系統呼叫:檔案描述子、低階的 read 和 write、open、creat、close 和 unlink,以及用 lseek 隨機存取。隨後是三個較完整的例子:fopen 和 getc 的實作、一個列出目錄的程式,以及一個記憶體配置器。導言指出,雖然本章部分內容是 UNIX 特有的,但它也展示了標準函式庫的一種實作可以如何完成。

附錄A–C:Reference Manual(參考手冊);Standard Library(標準函式庫);Summary of Changes(變更摘要)

附錄A是一份參考手冊,面向程式設計師而非編譯器編寫者,以較小的篇幅傳達 ANSI 標準的要點,最後附有文法。附錄B按標頭檔逐一概述標準函式庫,從 stdio.h 到 limits.h 和 float.h。附錄C列出了相對於第一版原始語言的變化。

核心概念

第1–3章:語言核心

  • 函式原型:列出參數型別的 ANSI 宣告形式,導言稱之為對大多數程式設計師來說最重要的變化。
  • 型別轉換:在表示式中組合不同型別的值時遵循的規則。
  • 按位運算子:作用於整數各個二進位制位的運算子。
  • 結構化控制流:if-else、switch、while、for、do-while、break 和 continue。

第4–6章:程式結構、指標與結構

  • 作用域與外部變數:程式的哪些部分能看到某個名字,包括跨原始檔共享的變數。
  • 前處理器:在正式編譯之前進行的巨集替換、檔案包含和條件編譯。
  • 指標運算:在陣列內部計算地址,以及指標與陣列之間的密切關係。
  • 自我參照結構:包含指向同類型結構的指標的結構,用來建構連結串列和樹。

第7–8章:函式庫與系統

  • 標準函式庫:由 ANSI 定義的函式和標頭檔集合,使輸入、輸出及其他系統存取具有可移植性。
  • 系統呼叫:由作業系統提供的 read、write、lseek 等低階操作。
  • 記憶體配置:顯式管理記憶體,以一個記憶體配置器為例說明。

評析

優點

  • 簡潔而精確。 作者有意讓本書保持短小,因為這門語言本身就小;整門語言、標準函式庫概要和參考手冊加起來不到300頁。出版社引用了 Bjarne Stroustrup 的評價,他稱讚教學各章看似輕鬆簡單的風格和參考手冊的乾淨利落。
  • 從完整的程式中學習。 序言強調書中是直接從正文測試過的完整、真實的程式,練習則要求讀者修改這些程式;作者還力求展示有用的演算法以及良好風格和合理設計的原則。示例程式可以從出版社下載,每章一個目錄。
  • 出自語言設計者之手。 參考手冊和對標準的講解出自定義 C 語言的人,而導言對語言的缺點也很坦率,承認有些運算子的優先順序不對、部分語法還可以更好。
  • 通向系統程式設計的橋梁。 第8章展示了函式庫如何建立在系統呼叫之上,並以一個記憶體配置器收尾,把語言與作業系統和函式庫的工作原理連結起來。

局限

  • 不是第一本程式設計書。 序言直言本書不是程式設計入門手冊,假定讀者熟悉變數、賦值、迴圈和函式;新手也能跟著讀,但最好有經驗更豐富的人幫助。
  • 描述的是1988年的 ANSI C。 本書按1988年 ANSI 標準的定義來描述 C。此後 C 標準的修訂沒有涉及,讀者需要從別處學習新特性和當前的函式庫用法。
  • 講語言,不講資料結構。 導言說明本書不是資料結構與演算法的參考書;在必須取捨時,作者把重點放在語言上。
  • 勘誤與印次。 Ritchie 維護了一份已出版版本的已知錯誤清單,其中許多已在後來的印次中更正;使用舊書的讀者應當參考它。

在課程中的定位

本入門程式設計課程中的其他書大多是為從未編過程的人寫的。Matthes 的 Python Crash Course 先用短小的練習教授 Python 的核心,再進入三個專案;Felleisen 等人的 How to Design Programs 用隨學生一起成長的教學語言講授系統的設計方法;Downey 的 Think Python 和 Guttag 的 Introduction to Computation and Programming Using Python 透過 Python 介紹電腦科學。Kernighan 和 Ritchie 以這樣的第一門課為前提,把讀者帶到更低的層次:記憶體、地址、指標,以及高階語言所隱藏的作業系統介面。

Abelson 和 Sussman 的 Structure and Interpretation of Computer Programs 則走向相反的方向:抽象、高階過程和直譯器。兩本都讀,可以看到程式設計的兩端:從一門小語言向上建構抽象,以及直接管理機器。讀完一本 Python 書的學生,接下來讀本書正合適,也可以與電腦組成或作業系統課程同時閱讀。

如何使用本書

本書適合已經會用某種語言程式設計、想認真學習 C 的學生,尤其是將要學習系統程式設計、嵌入式系統開發或作業系統課程的學生。

  • 在鍵盤前讀第1章。 輸入並執行每一個例子;作者認為,學習一門語言的方法就是用它寫程式。
  • 核心: 按順序讀第2–6章。在第5章上花最多的時間;在進入第6章之前,用小的測試程式和記憶體示意圖把指標與陣列弄明白。
  • 函式庫與系統: 寫實用程式離不開第7章。第8章初讀時可以跳過,但對修讀系統類課程的學生收穫很大;記憶體配置器值得逐行研讀。
  • 參考: 附錄A和B用於查閱,而不必通讀。

一定要做練習:練習簡短,與例子緊密相連,許多是對正文程式的擴展。用現代編譯器並開啟警告進行編譯,利用出版社提供下載的示例程式和 Ritchie 的勘誤表核對正文。關於後來的 C 標準,應以最新的參考資料作補充。