1. 程式人生 > >記憶體對齊時為什麼結構體的最終大小需要是其最大成員大小的整數倍

記憶體對齊時為什麼結構體的最終大小需要是其最大成員大小的整數倍

本文主要記錄博主在研究記憶體對齊時遇到的一個疑問,及最終疑問的解答。

至於 什麼是記憶體對齊、為什麼要記憶體對齊、記憶體對齊的規則,網上一搜一大堆,這裡就不記錄了。

記憶體對齊時,結構體分配記憶體大小會滿足兩個條件:

1. 假設第一個成員的起始地址為0,每個成員的起始地址(startpos)必須是其資料型別所佔空間大小的整數倍。

2. 結構體的最終大小必須是其成員(基礎資料型別成員)裡最大成員所佔大小的整數倍。

其中,第一條起始地址特殊要求的原因(實際上就是記憶體對齊的原因)網上依然一搜一大把,主要是提高處理器訪問記憶體的速度。

但第二條又是為什麼呢?為什麼要在所有成員都對齊以後又對整體大小做了要求?

查了一圈沒有查到,最後在stackoverflow似乎找到了答案。

貼上原文地址:http://stackoverflow.com/questions/10309089/why-does-size-of-the-struct-need-to-be-a-multiple-of-the-largest-alignment-of-an

以下是看完帖子後的個人理解,若是不對還請各位指出。

個人理解:第二條實際上還是為了記憶體對齊,如果沒有第二條來善後,那第一條的工作就有可能白做了。舉個例子

struct st{
    int32_t a;
    int8_t  b;
};

struct st arr[N];

結構體 st 如果在最後沒有進行填充則應該是5個位元組,若做了填充則是8個位元組。而底下陣列arr的地址分配則會受到結構體 st 大小的影響。

假設陣列的起始地址為0,那麼

st 為5位元組時,arr[0] 佔用 0-4,arr[0].a的startpos為0,arr[0].b的startpos為4;arr[1] 佔用 5-9,arr[1].a的startpos為5,arr[1].b的startpos為9。可以看到arr[1]的內部成員a並沒有對齊(startpos不是其資料型別大小的整數倍),借用帖子裡的話 arr[1].a 會cross lines。

st 為8位元組時,arr[0] 佔用 0-7,arr[0].a的startpos為0,arr[0].b的startpos為4;arr[1] 佔用 8-15,arr[1].a的startpos為8

,arr[1].b的startpos為12。依次類推數組裡所有結構體成員及所有結構體的內部成員都會對齊。

因為基礎資料型別的資料大小無非就是1 2 4 8 16位元組,若結構體的總大小是最大基礎成員大小的整數倍,那麼也就一定是其他任一基礎成員大小的整數倍,那麼每個結構體的startpos就一定是其任一基礎成員大小的整數倍 ,這樣的話,兩條規則結合在一起就保證了所有基礎型別資料、非基礎型別資料全部對齊。