聯合體與枚舉是結構體之外的兩種重要構造型別。聯合體實現記憶體重疊共享,枚舉提供具名常數集合,兩者解決不同領域的問題。
typedef union {
short count; // 2 bytes
float weight; // 4 bytes
float volume; // 4 bytes
} Quantity; // 大小 = max(2,4,4) = 4 bytes
typedef struct {
const char *color;
Quantity amount;
} Bike;
int main() {
Bike b1 = {"Red", .amount.count = 5}; // 用 count
Bike b2 = {"Blue", .amount.weight = 10.5f}; // 用 weight
// 危險:寫入 weight 後讀取 count
b2.amount.weight = 10.5f;
printf("count: %d\n", b2.amount.count); // 垃圾值!位元模式不同
return 0;
}
關鍵風險:聯合體無型別標記,程式設計師需自行追蹤當前有效成員。誤讀導致未定義行為。
typedef enum {
RED, // 0
BLACK, // 1
BLUE, // 2
GREEN // 3
} Color;
Color favorite = BLUE;
printf("%d\n", favorite); // 輸出 2
// 自定義值
typedef enum {
ERR_OK = 0,
ERR_MEM = -1,
ERR_IO = -2,
ERR_NET = -3
} ErrorCode;
// 位元旗標 (配合位運算)
typedef enum {
READ = 1 << 0, // 1
WRITE = 1 << 1, // 2
EXEC = 1 << 2, // 4
ALL = READ | WRITE | EXEC // 7
} Permission;
| 場景 | 推薦 | 理由 |
|---|---|---|
| 同一資料多種解讀(如 IPv4 地址:整數/4字節陣列) | 聯合體 | 零開銷記憶體重疊 |
| 互斥的資料型別(訊息類型決定承載結構) | 聯合體 + 標記欄位 | 手動實現 tagged union |
| 固定集合的離散值(狀態碼、顏色、錯誤碼) | 枚舉 | 型別安全、除錯器顯示名稱 |
| 位元旗標組合(權限、屬性標記) | 枚舉 + 位運算 | 語意清晰、編譯期計算 |
| 需儲存多種不同型別資料同時存在 | 結構體 | 各成員獨立記憶體 |
typedef enum { INT_TYPE, FLOAT_TYPE, STR_TYPE } DataTag;
typedef struct {
DataTag tag;
union {
int i;
float f;
char *s;
} value;
} Variant;
void print_variant(Variant v) {
switch (v.tag) {
case INT_TYPE: printf("%d\n", v.value.i); break;
case FLOAT_TYPE: printf("%f\n", v.value.f); break;
case STR_TYPE: printf("%s\n", v.value.s); break;
}
}
此模式在 C 模擬多態、解析 JSON/協議緩衝區時極常見。