枚舉與結構體是 C 語言自定義類型的兩大基石。本文系統整理語法、初始化、記憶體佈局、位元組對齊、指標操作、函式傳遞、位域等核心知識,並附帶實用程式碼片段。
enum Color { RED, YELLOW, GREEN }; // 隱性值 0,1,2
enum Color { RED=1, YELLOW, GREEN=5 }; // 顯性指定,YELLOW=2
enum Color c = RED; // 宣告變數
c = 99; // 合法!枚舉本質是 int,無類型限制
printf("%d", c); // 輸出 99
// 枚舉優於 #define:有類型、可除錯、有作用域
// 枚舉技巧:加尾項 NUM_COLORS 自動獲得成員數量
enum Color { RED, YELLOW, GREEN, NUM_COLORS }; // NUM_COLORS = 3
struct Date {
int month;
int day;
int year;
};
// 宣告與初始化
struct Date today = {7, 31, 2024}; // 順序初始化
struct Date tomorrow = {.month=8, .day=1}; // C99 指定初始化器,未指定為0
struct Date *p = &today;
// 成員存取
today.month = 8; // 直接存取
p->day = 1; // 指標存取 (等價於 (*p).day)
// 整體操作
struct Date copy = today; // 逐位元複製 (淺拷貝)
today = (struct Date){12,25,2024}; // 複合字面值 (C99)
// 陣列
struct Date dates[10];
dates[0] = today;
// 函式傳遞
void print_date(struct Date d) { ... } // 值傳遞 (複製)
void modify_date(struct Date *d) { ... } // 指標傳遞 (可修改)
struct Example {
char c; // offset 0, size 1
// 3 bytes padding
int i; // offset 4, size 4
double d; // offset 8, size 8 (對齊至8)
}; // sizeof = 24 (非 1+4+8=13)
// 對齊規則:每個成員偏移量必須是其大小的倍數
// 結構體總大小必須是最大成員對齊需求的倍數
// #pragma pack(n) 可改變對齊 (非標準,慎用)
struct Flags {
unsigned int a : 1; // 佔1位
unsigned int b : 3; // 佔3位
unsigned int c : 4; // 佔4位
}; // 共用一個 unsigned int (通常4位元組)
// 注意:位域跨平台佈局不固定,不可用於網路協定/檔案格式
struct Impl; typedef struct Impl* Handle; 隱藏實作細節struct { size_t len; char data[]; } 動態大小結構struct Node { void* data; struct Node* next; }struct { void (*func)(void*); void* arg; }sizeof(struct) 包含填充位元組,memcpy 複製整個結構體含填充(struct Type){...} 是暫時物件,生命週期至區塊結束熟練掌握枚舉與結構體,是編寫清晰、高效、可維護 C 程式的關鍵一步。