現象:結構體大小不等於成員大小之和
struct student { short s; long b; } stu;
printf("%d", sizeof(stu)); // 輸出 8,而非預期的 6 (2+4)
核心原因:編譯器為了存取效率進行對齊
- 處理器以固定寬度(如 4 位元組)讀取記憶體
- 對齊規則:成員偏移量必須是其大小的整數倍;結構體總大小必須是最大成員大小的整數倍
- 編譯器在成員間插入填充位元組
圖解:4 位元組對齊下的佈局
地址偏移: 0 1 2 3 4 5 6 7
成員: | s(short) | padding | b(long) |
大小: 2 bytes 2 bytes 4 bytes
總計: 8 bytes
巢狀結構體對齊實戰
struct student { short s; long b; }; // 大小 8
struct teacher {
char c;
struct student stu;
double e;
};
| 編譯模式 | sizeof(student) | sizeof(teacher) | 關鍵佈局說明 |
| 4 位元組對齊 | 8 | 20 | char 獨佔 4 位元組塊;student 佔 2 塊;double 佔 2 塊 → 5×4=20 |
| 8 位元組對齊 | 8 | 24 | char 佔 8 位元組塊前半部;student 緊接;double 需 8 位元組對齊,導致額外填充 |
對齊規則總結
- 第一個成員偏移為 0
- 後續成員偏移 = min(當前對齊數, 成員大小) 的整數倍
- 結構體總大小 = max(當前對齊數, 最大成員大小) 的整數倍
- 可用
#pragma pack(n) 或 GCC __attribute__((packed)) 改變對齊數
實用技巧
- 成員按大小遞減排序可減少填充
- 嵌入式開發關注記憶體佔用時可打包結構體
- 網路協議/檔案格式解析需精確控制佈局,建議配合靜態斷言驗證