CPU 訪問內存時,若地址對齊到其數據總線寬度的整數倍(如 4 字節對齊讀取 int),可**單指令完成**;否則需多次總線事務,甚至觸發硬件異常(部分架構)。編譯器自動插入填充字節以滿足對齊要求,這是「空間換時間」的經典權衡。
#pragma pack 時)sizeof(結構體) 必須為所有成員對齊要求的最大值的整數倍,不足補齊。| 結構體定義 | sizeof | 內存佈局(x=填充) |
|---|---|---|
struct { short a,b,c; } | 6 | a1 a2 b1 b2 c1 c2 |
struct { long a; short c; } | 8 | a1 a2 a3 a4 c1 c2 x x |
struct { int a; char b; short c; } | 8 | a1 a2 a3 a4 b1 x c1 c2 |
struct { char a; int b; short c; } | 12 | a1 x x x b1 b2 b3 b4 c1 c2 x x |
struct { int a; double b; short c; } | 24 | a(4) x(4) b(8) c(2) x(6) |
| 巢狀結構體 B 包含 A | 48 | 按規則 2、3 遞歸計算 |
#pragma pack(n) 強制對齊實戰指定最大對齊數 n(1/2/4/8/16),實際對齊 = min(成員大小, n)。
| 結構體 | pack(1) | pack(2) | pack(4) | 默認 |
|---|---|---|---|---|
A (int, double, short) | 14 | 14 | 16 | 24 |
| B (含 A) | 30 | 30 | 36 | 48 |
恢復默認:#pragma pack() 或 #pragma pack(pop)(配合 push)。
struct __attribute__((aligned(8))) S { ... }; // 整體 8 字節對齊
struct __attribute__((packed)) S { ... }; // 等同 pack(1)
struct { char a:2; char b:4; char c:5; } // sizeof=2 (GCC/VC6 同)
struct { int a:20; int b:20; int c:3; } // sizeof=8 (跨越兩個 int)
struct { int a:4; char b; int c:3; } // VC6=12, GCC=4 (壓縮)
#pragma pack(1) 或 __attribute__((packed)) 確保佈局一致。alignas(64) (C++11) 防止偽共享。memcpy 結構體,用 Protocol Buffers、FlatBuffers 等顯式序列化庫。offsetof(T, member) 查看成員偏移,sizeof(T) 驗證總大小。結構體對齊是 C 語言「抽象機器」與「真實硬件」交鋒的縮影。吃透三大規則、善用 pack、理解位域差異,才能寫出既高效又可移植的系統級代碼。