Brian Kernighan & Dennis Ritchie:the C Programming Language@1988 (第2版)
這份文件(似乎是一本 C 語言經典教材的目錄、前言及部分內容)主要圍繞著 C 語言的核心概念、結構化程式設計方法,以及基於 ANSI 標準的語言特性進行闡述。其主要論點可以歸納為以下幾個方面:
-
C 語言作為一種通用、高效且可移植的程式語言:
文件開頭的前言即指出 C 語言是一種「通用程式語言」,擁有「簡潔的表達方式、現代化的流程控制和資料結構,以及豐富的運算子」。它並非「非常高階」或「龐大」的語言,也不專用於特定應用領域,但其「缺乏限制」和「通用性」使其在許多任務中比其他看似更強大的語言更方便有效。這本書的目標就是幫助讀者學習如何在 C 語言中有效地撰寫程式,並強調其易於學習且隨經驗增長而益發順手的特性。這構成了整本書的基礎論點:C 語言值得學習與掌握,因為它是一種強大且靈活的工具。 -
結構化程式設計的重要性:
文件透過早期章節的範例(如華氏-攝氏溫度轉換、字元計數、行計數、單字計數)展示了如何使用變數、基本運算子、流程控制(if-else、while、for)來解決簡單問題。然而,隨著問題複雜性的增加(如長度最長的行程式),文件立即引入了「函式」(Functions)的概念。函式被視為將大型計算任務分解為較小部分的便捷方法,能「封裝」計算細節,使程式的其他部分無需關心其內部實現,從而提高清晰度和可維護性。這強調了將程式分解為多個獨立函式是良好程式設計實踐的核心原則。函式之間的溝通方式(透過引數和返回值,或共用外部變數)也被詳細討論,並提醒過度依賴外部變數可能導致程式結構不佳和資料連接不明確的問題。 -
C 語言的核心建構積木:型別、運算子和表達式:
文件詳細闡述了 C 語言的基礎元素。-
型別(Types): 變數和常數是基本資料物件,型別決定了它們可以擁有的值集合以及可以對其執行的操作。文件介紹了基本型別(
char,int,float,double)及其修飾符(short,long,signed,unsigned,long double),並解釋了它們的大小可能因機器而異,但遵循一定的約束。結構(struct)和聯合(union)作為複合型別被引入,用於組織相關資料。 -
運算子(Operators): C 語言以其豐富的運算子集而聞名。文件覆蓋了算術運算子、關係運算子、邏輯運算子、位元運算子、指派運算子、增量和減量運算子,以及條件運算子。詳細解釋了它們的功能、運算元要求、優先順序和結合性。特別強調了邏輯運算子 (
&&,||) 的短路求值特性,以及增量/減量運算子 (++,--) 的前綴與後綴形式的差異。位元運算子 (&,|,^,<<,>>,~) 則展示了 C 語言處理低階細節的能力。 - 表達式(Expressions): 變數和常數結合運算子構成表達式。文件解釋了表達式的求值過程,包括型別轉換規則(自動晉升、隱式轉換、強制轉型 Cast)。一個關鍵論點是,理解型別轉換對於避免潛在的錯誤和確保程式行為的正確性至關重要,尤其是在混合型別的運算中。運算子的優先順序和結合性決定了表達式的解析方式,儘管內部求值順序(除了一些特定運算子外)是不確定的,這對涉及副作用的表達式有影響,提醒程式設計師應避免依賴未指定的求值順序。
-
型別(Types): 變數和常數是基本資料物件,型別決定了它們可以擁有的值集合以及可以對其執行的操作。文件介紹了基本型別(
-
指標與陣列的密切關係及其在 C 語言中的重要性:
這是 C 語言中最獨特且強大的特性之一,也是文件重點闡述的論點。-
指標(Pointers): 指標是儲存變數記憶體位址的變數。文件解釋了如何宣告指標,使用
&運算子獲取位址,使用*運算子進行間接存取(Dereferencing)。強調指標在函式引數傳遞(模擬傳址呼叫)、操作記憶體及提高效率方面的作用。 - 陣列(Arrays): 陣列是相同型別物件的連續集合,在 C 語言中是零索引的。
-
關係: 文件明確指出,在 C 語言中,指標和陣列之間存在著「密切的關係」。陣列名稱本身在大多數情況下代表陣列第一個元素的位址。陣列索引表示法
a[i]被定義為等同於指標算術表示法*(a+i)。這意味著對陣列的任何操作都可以透過指標來完成,反之亦然。 - 指標算術(Pointer Arithmetic): 指標可以與整數相加或相減,其增量或減量的大小會根據指標指向的物件型別自動調整,這使得指標能方便地遍歷陣列或相關記憶體區域。兩個指向同一陣列元素的指標可以相減,結果表示它們之間的元素數量。
-
應用: 文件透過範例(如
strlen,strcpy,strcmp, 記憶體分配alloc/afree, 排序程式)展示了如何利用指標和陣列的關係來編寫更緊湊、高效的程式碼,特別是在處理字串、動態記憶體和複雜資料結構(如指標陣列)時。這種關係是 C 語言高效處理記憶體的關鍵,但同時也需要程式設計師高度警惕,避免無效的指標操作導致未定義的行為。
-
指標(Pointers): 指標是儲存變數記憶體位址的變數。文件解釋了如何宣告指標,使用
-
結構化資料的組織與操作:
結構 (struct) 允許將不同型別的相關變數組合成一個單一單元。這對於組織複雜資料非常有用,例如在圖形處理中表示點和矩形,或在編譯器中表示符號表條目。-
結構成員存取: 文件解釋了使用
.運算子存取結構成員,以及使用->運算子透過指標存取結構成員。 - 結構與函式: 討論了將結構作為函式引數傳遞、作為返回值返回,以及傳遞結構指標的方法。ANSI 標準明確支援結構的整體指派、傳遞和返回。
- 結構陣列: 展示了如何宣告和初始化結構陣列,並將其應用於關鍵字計數程式中。
- 自參考結構(Self-referential Structures): 這是構建連結串列和樹等動態資料結構的基礎。文件透過二元搜尋樹的例子,展示了結構如何包含指向同型別結構的指標,以及如何使用遞歸函式來操作這些結構。
- 聯合(Unions): 作為一種特殊的結構,聯合允許在同一塊記憶體中儲存不同型別的值,這對於節省空間或處理具有多種可能表示形式的資料非常有用,但需要程式設計師手動追蹤當前儲存的型別。
- 位元欄位(Bit-fields): 作為結構的特殊成員,位元欄位允許程式設計師指定成員佔據的精確位元數,這對於處理硬體介面或需要極度節省空間的情況很有用,但具有較高的實現依賴性。
-
結構成員存取: 文件解釋了使用
-
標準函式庫的角色與輸入/輸出:
C 語言本身並不包含輸入/輸出功能,這些功能由標準函式庫提供。-
標準輸入/輸出: 文件介紹了標準輸入 (
stdin)、標準輸出 (stdout) 和標準錯誤 (stderr) 流,以及基本的字元 I/O 函式 (getchar,putchar) 和格式化 I/O 函式 (printf,scanf)。 -
檔案存取: 擴展到處理具名檔案,引入了檔案指標 (
FILE*) 和檔案操作函式 (fopen,fclose,getc,putc,fscanf,fprintf)。 -
錯誤處理: 說明了如何使用
stderr輸出錯誤訊息,以及exit函式來終止程式並返回狀態碼。 -
其他函式: 簡要提及了標準庫中的其他常用功能,如字串處理 (
<string.h>)、字元分類測試 (<ctype.h>)、記憶體管理 (malloc,freein<stdlib.h>)、數學函式 (<math.h>) 等。標準庫是 C 語言環境的重要組成部分,提供了大量可移植的工具供程式設計師使用。
-
標準輸入/輸出: 文件介紹了標準輸入 (
-
低階介面與系統呼叫(以 UNIX 為例):
C 語言被設計為可以方便地與作業系統底層互動。文件以 UNIX 系統為例,展示了如何使用系統呼叫進行低階 I/O (read,write) 和檔案系統操作 (open,creat,close,lseek,stat, 目錄讀取)。這部分內容雖然具體實現依賴於作業系統,但展示了 C 語言如何提供對系統資源的直接存取,以及標準庫函式如何建構在這些低階介面之上。儲存分配程式 (malloc,free) 的實現範例進一步展示了如何管理記憶體,並處理硬體相關的對齊問題,體現了 C 語言在系統程式設計中的應用。 -
前處理器及其功能:
前處理器是 C 翻譯過程的第一步,在實際編譯之前對原始碼進行文字處理。-
巨集替換 (
#define): 用於定義符號常數和帶參數的巨集,實現代碼替換,可以避免使用「魔術數字」並提高代碼的可讀性和可維護性。新標準增加了字符串化 (#) 和標記連接 (##) 運算子,增強了巨集的功能。 -
檔案包含 (
#include): 用於將其他檔案的內容包含到當前原始碼中,常用於包含頭檔案以共用宣告和巨集,確保不同原始碼檔案使用一致的定義,減少錯誤。 -
條件編譯 (
#if,#ifdef,#ifndef,#elif,#else,#endif): 允許根據條件(例如是否定義了某個巨集)有選擇地編譯程式碼的不同部分,這對於管理不同平台或配置版本的程式碼非常有用。
-
巨集替換 (
-
ANSI 標準的影響:
貫穿整份文件的一個重要背景是 ANSI C 標準的引入。前言和附錄 C 都強調了標準化的重要性。- 目的: 創建一個「明確且機器獨立」的 C 語言定義,同時保留其精神。
- 主要變更: 標準化並正式化了許多現有的實踐(如結構指派、列舉),引入了新的特性(如函式原型用於更嚴格的型別檢查和參數轉換),指定了一個標準函式庫以提高可移植性,並釐清了許多原先未明確定義的行為(如特定指標操作、型別轉換規則、副作用的處理等)。
- 影響: 鼓勵程式設計師使用新風格的函式宣告和定義以利用更好的錯誤檢查,並依賴標準庫提供的可移植功能。雖然舊風格仍然為了相容性而保留,但文件明確推薦使用新標準的特性。
總結來說,這份文件最主要的論點是:C 語言是一種強大、簡潔且靈活的程式語言,尤其擅長處理低階記憶體操作和系統互動。學習 C 語言需要掌握其核心建構積木(型別、運算子、表達式)、結構化程式設計方法(函式、流程控制),以及最重要的指標和陣列概念。基於 ANSI 標準的 C 語言(K&R 第二版所描述的)透過標準化和新特性(特別是函式原型)提高了語言的嚴謹性和可移植性,而標準函式庫提供了豐富的工具來支援廣泛的程式設計任務。透過大量實際範例的閱讀、編寫和修改,讀者可以有效地掌握 C 語言的精髓。
comments
comments for this post are closed