struct data1 { BYTE a; }; // sizeof = 1
struct data2 { BYTE a; LONG b; }; // sizeof = 8 (而非 1+4=5)
初學者常困惑:明明成員只有 1 + 4 = 5 個位元組,為何編譯器報告 8?這涉及 C++ 核心機制——記憶體對齊。
位址偏移: 0 1 2 3 4 5 6 7 內容: a pad pad pad b b b b 大小: 1 3 4
BYTE a 置於偏移 0,大小 1。LONG b 需 4 位元組對齊,下一個可用的 4 的倍數位址是 4,故在 1-3 插入 3 位元組填充。LONG b 佔據偏移 4-7。| 規則 | 說明 |
|---|---|
| 成員對齊 | 每個成員偏移量必須是 min(成員大小, 編譯器對齊數) 的整數倍 |
| 結構體對齊 | 總大小必須是所有成員對齊需求最大值的整數倍 |
| 宣告順序影響大小 | struct { char c; double d; } = 16 bytes;struct { double d; char c; } = 16 bytes(尾部填充) |
| 巢狀結構體 | 內部結構體作為整體按其對齊需求對齊 |
| 空結構體 | C++ 標準規定至少 1 byte,確保不同物件有不同位址 |
// 壞:16 bytes
struct Bad { char c; double d; int i; };
// 好:16 bytes(同樣大小,但較合理)
// 更好:將大型別集中
struct Good { double d; int i; char c; }; // 16 bytes,無內部填充
#pragma pack 強制封裝(謹慎使用)#pragma pack(push, 1) // 1 位元組對齊
struct Packed { BYTE a; LONG b; }; // sizeof = 5
#pragma pack(pop)
風險:可能導致非對齊存取效能下降、硬體異常、與外部庫 ABI 不相容。
alignas (C++11) 指定對齊struct Aligned16 { alignas(16) BYTE a; LONG b; }; // 起始位址 16 位元組對齊
Debug → Windows → Memory 觀察位址;/d1 reportSingleClassLayout 編譯選項輸出佈局報告。-fdump-record-layouts 或 GDB 中 ptype/o struct_name。跨平台傳輸結構體時,絕不可直接 send(sock, &struct, sizeof(struct), 0)。必須:
long 在 32/64 位元系統不同)。結構體大小大於成員總和,是編譯器為了CPU 存取效能自動插入填充位元組的結果。理解對齊規則、善用宣告順序優化、謹慎使用 #pragma pack、網路傳輸採用標準序列化協議,是 C++ 系統級開發者的必備功力。