結構填充
假設這個 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) == 4
和 sizeof(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 位元組邊界上。