struct、union、enum 與 typedef
基本型別給你單一的值,但真實資料是成束出現的:一個點有 x 與 y;一個日期有日、月、年。C 讓你能從基本型別建立自己的複合型別。做這件事的四個工具是 struct、union、enum、typedef——它們分別讓你命名一筆記錄、一個共用的槽、一組選項、以及一個簡寫。
struct 把數個具名欄位組在一起、它們同時全部存在、一個接一個地排放:「struct Point { int x; int y; };」是一筆同時握著 x 與 y 的記錄,以 p.x 與 p.y 存取。union 也列出數個欄位,但它們「共用」同一塊記憶體,所以一次只有一個有意義——它是一種把同樣的位元當作不同型別來看的方式,大小是其最大成員的大小。enum 定義一組具名整數常數,例如「enum Day { MON, TUE, WED };」,給一份固定清單可讀的名字。typedef 只是替既有型別建立別名:「typedef struct Point Point;」讓你到處能寫 Point 而非 struct Point。(struct 也能包含位元欄位,把數個小值塞進一個欄位的位元裡,另行說明。)
為什麼重要:struct 是 C 程式用來建模它們所處理之物的方式——檔案、網路封包、樹節點——把鬆散的變數變成有意義的記錄。enum 讓程式碼自我說明、可供 switch。typedef 馴服冗長的型別名稱。誠實的告誡是關於 union:因為所有成員重疊,語言並不追蹤目前哪個成員有效;讀取你並非最近才寫入的成員通常不是你要的(讀取與寫入不同的成員是實作定義行為或更糟)。要安全使用 union,需要紀律,通常搭配一個標籤 enum。
struct Point { int x; int y; }; typedef struct Point Point; /* 現在 'Point' 是簡寫 */ Point p = { 3, 4 }; /* p.x == 3、p.y == 4 */ enum Day { MON, TUE, WED }; /* MON==0、TUE==1、WED==2 */ union Value { int i; float f; }; /* i 與 f 共用同樣的位元組 */
struct 同時儲存所有欄位;union 把它們重疊在共用記憶體中;enum 為整數常數命名;typedef 給一個較短的別名。
union 的成員共用同一塊記憶體,所以一次只有一個有效、而語言不追蹤是哪個——請自己追蹤,通常用一個搭配的 enum 標籤。struct 的成員各有自己的儲存,且為了對齊它們之間可能有填充。