記憶體與指標

對齊與填充

你或許以為結構的欄位會背靠背、毫無縫隙地排在一起,但它們常常不是。CPU 偏好——在某些機器上甚至要求——每種值都從「其大小的整數倍」這樣整齊的位址開始。對齊(alignment)就是這條規則,而填充(padding)是編譯器插入、用來讓每個欄位保持正確對齊的未使用填補位元組。

具體而言,一個 4 位元組的 int 在其位址為 4 的倍數時(如 0x1000 或 0x1004)是自然對齊的,8 位元組的值則要在 8 的倍數處。當你佈置一個結構時,編譯器可能得把某個欄位往前推以符合它的對齊,在縫隙留下填充位元組;它也可能加上尾端填充,好讓在「該結構的陣列」中每個元素都保持對齊。這就是為什麼一個結構的 sizeof 可能大於其欄位大小的總和,也是為什麼欄位順序很重要:把最寬的成員放在前面、或按大小分組,能藉由消除內部填充把結構縮小。一個型別的對齊需求由 alignof 回報,口訣是:一個型別的對齊等於它最大的純量成員的大小。

為什麼要在意?對齊的存取較快,而在某些架構上未對齊的存取會直接出錯;這也是為什麼 malloc 回傳的記憶體適合任何型別地對齊。誠實的提醒是:確切的填充是實作定義的——它取決於目標平台的 ABI——所以你絕不該假設某種特定佈局、絕不該依賴縫隙裡裝著任何值,也絕不該逐位元組(用 memcmp)比較兩個結構值並期待填充相符,因為填充位元組可能裝著任意殘留。

struct S { char c; int n; }; 常常 sizeof(struct S) == 8,而非 5:char(1 位元組)在偏移 0,接著 3 個填充位元組,然後 int n 在偏移 4 以維持 4 位元組對齊。改成 { int n; char c; } 順序,你仍然得到 8(陣列用的尾端填充)。

填充使結構大於其欄位的總和;欄位順序有影響。

確切的填充與對齊由實作與 ABI 定義,不是 C 標準所保證,所以絕不要寫死偏移、絕不要假設填充位元組為零,並避免對整個結構用 memcmp——即使所有真實欄位都相等,填充位元組也可能不同。

又稱
data alignmentstruct padding記憶體對齊