包裝結構
預設情況下,結構用 C 填充。如果要避免此行為,則必須明確請求它。在 GCC 下,它是 __attribute__((__packed__))
。在 64 位計算機上考慮此示例:
struct foo {
char *p; /* 8 bytes */
char c; /* 1 byte */
long x; /* 8 bytes */
};
該結構將自動填充到 has8-byte
對齊,如下所示:
struct foo {
char *p; /* 8 bytes */
char c; /* 1 byte */
char pad[7]; /* 7 bytes added by compiler */
long x; /* 8 bytes */
};
所以 sizeof(struct foo)
會給我們 24
而不是 17
。這是因為 64 位編譯器在每個步驟中以 8 位元組的字對儲存器進行讀/寫操作,並且當嘗試在儲存器中寫入 char c;
時,顯而易見的是一個完整的 8 位元組(即字)取出並僅消耗第一個位元組它及其七個連續的位元組保持為空,並且對於結構填充的任何讀寫操作都不可訪問。
結構包裝
但是如果新增屬性 packed
,編譯器將不會新增填充:
struct __attribute__((__packed__)) foo {
char *p; /* 8 bytes */
char c; /* 1 byte */
long x; /* 8 bytes */
};
現在 sizeof(struct foo)
將返回 17
。
通常使用包裝結構:
- 為了節省空間。
- 格式化資料結構以通過網路傳輸,而不依賴於網路的每個節點的每個架構對齊。
必須考慮到某些處理器(如 ARM Cortex-M0)不允許未對齊的記憶體訪問; 在這種情況下,結構打包可能導致未定義的行為並可能導致 CPU 崩潰。