struct s1 { char c1, c2, c3, c4; }; // sizeof = 4
struct s2 { char a; struct s1 s; }; // sizeof = ?
錯誤預期:將 s1 視為整體(4 字節),a 1 字節 + 填充 3 字節 + s1 4 字節 = 8 字節。
實測結果 (GCC/VS2010):sizeof(s2) = 5。
記憶體佈局:
s2: | a (1) | s.c1 (1) | s.c2 (1) | s.c3 (1) | s.c4 (1) | 偏移: 0 1 2 3 4
s 的首地址對齊要求為 char(1 字節),非 4 字節。結構體總長按最寬成員 char 對齊(1 字節),故無尾部填充。
struct S1 { char a; short b; }; // sizeof = 4 (a+1填充+b)
struct S2 { char a; struct S1 s; }; // sizeof = ?
實測:sizeof(S2) = 6。
佈局:
S2: | a (1) | 3填充 | s.a (1) | 1填充 | s.b (2) | 偏移: 0 1-3 4 5 6-7? 實際 6 字節
s 首地址對齊至 short(2 字節)倍數(偏移 4)。S2 總長對齊至 short(2 字節)倍數 → 6。
struct S { char a, b; short c; }; // sizeof = 4
// 佈局: a(1) b(1) c(2) → 緊湊無填充
巢狀結構體保持內部佈局不變,作為整體按其最寬成員對齊放入外層結構,而非按巢狀結構體總大小對齊。
CPU 讀取寬度有限(32 位機單次 4 字節)。強制大結構體按總大小對齊會浪費大量空間,且超過總線寬度仍需多次讀取,收益遞減。編譯器選擇按最寬基本類型對齊,平衡空間與存取效率。