結構填充

假設這個 struct 是用 32 位編譯器定義和編譯的:

struct test_32 {
    int a;      // 4 byte
    short b;    // 2 byte
    int c;      // 4 byte    
} str_32;

我們可能期望這個 struct 只佔用 10 個位元組的記憶體,但是通過列印 sizeof(str_32),我們看到它使用了 12 個位元組。

發生這種情況是因為編譯器將變數對齊以便快速訪問。一種常見的模式是,當基型別佔用 N 個位元組時(其中 N 是 2 的冪,如 1,2,4,8,16 - 並且很少更大),變數應該在 N 位元組邊界上對齊( N 個位元組的倍數)。

對於 sizeof(int) == 4sizeof(short) == 2 所示的結構,常見的佈局是:

  • int a; 儲存在偏移量 0; 4 號。
  • short b; 儲存在偏移量 4; 2 號。
  • 偏移量為 6 的未命名填充; 2 號。
  • int c; 儲存在偏移量 8; 4 號。

因此 struct test_32 佔用 12 個位元組的記憶體。在此示例中,沒有尾隨填充。

編譯器將確保從 4 位元組邊界開始儲存任何 struct test_32 變數,以便結構中的成員正確對齊以便快速訪問。需要記憶體分配函式,如 malloc()calloc()realloc(),以確保返回的指標與任何資料型別的使用足夠對齊,因此動態分配的結構也將正確對齊。

最終可能出現奇怪的情況,例如 64 位 Intel x86_64 處理器(例如 Intel Core i7 - 執行 macOS Sierra 或 Mac OS X 的 Mac),在 32 位模式下進行編譯時,編譯器將 double 對齊 4 位元組邊界; 但是,在相同的硬體上,當在 64 位模式下編譯時,編譯器將 double 對齊在 8 位元組邊界上。