內存對齊

1、內存對齊的緣由

  大部分的參考資料都是如是說的:
ios

  一、平臺緣由(移植緣由):不是全部的硬件平臺都能訪問任意地址上的任意數據的;某些硬件平臺只能在某些地址處取某些特定類型的數據,不然拋出硬件異常。
  二、性能緣由:數據結構(尤爲是棧)應該儘量地在天然邊界上對齊。緣由在於,爲了訪問未對齊的內存,處理器須要做兩次內存訪問;而對齊的內存訪問僅須要一次訪問。數據結構


 


 

2、內存對齊的規定:

 
  1.數據成員對齊規則:結構(struct或聯合union)的數據成員,第一個數據成員放在offset爲0的地方,之後每一個數據成員存儲的起始位置要從該成員自身大小的整數倍開始(好比int在32位機爲4字節,則要從4的整數倍地址開始存儲)。編譯器在給結構體開闢空間時,首先找到結構體中最寬的基本數據類型,而後尋找內存地址能被該基本數據類型所整除的位置,做爲結構體的首地址。將這個最寬的基本數據類型的大小做爲上面介紹的對齊數。
 
   2.結構體做爲成員:若是一個結構裏有某些結構體成員,則結構體成員要從其內部最大元素大小的整數倍地址開始存儲。爲結構體的一個成員開闢空間以前,編譯器首先檢查預開闢空間的首地址相對於結構體首地址的偏移是不是本成員的整數倍,如果,則存放本成員,反之,則在本成員和上一個成員之間填充必定的字節,以達到整數倍的要求,也就是將預開闢空間的首地址後移幾個字節。
 
  3.結構體成員相對首地址偏移量必須是成員大小的整數倍,也就是內存對齊。
 
  4.結構體總大小必須是對齊模數的整數倍。
 


 


 

3、計算

#include <stdlib.h> #include <iostream> using namespace std; int main() { struct AA { char a; char b; char c; }; cout << sizeof(AA) << endl; system("pause"); } 

  這個比較簡單,能夠根據上面的表格能夠直接計算出來。性能

 


 

  來個有點難度的spa

#include <stdlib.h> #include <iostream> using namespace std; int main() { struct AA { char a; int b; char c; }; cout << sizeof(AA) << endl; system("pause"); }

  猜猜結果會是多少? 會是 5 嗎??3d

  來詳細瞭解一下:code

 

  實際上會如圖所示嗎???blog

  當以如圖的方式存放數據時,系統訪問char a 時,只需讀取一個字節,但當訪問 int b 的時候,先要讀取一個字節,在讀取四個字節,才能讀到int b的值。這樣系統在訪問數據時要先判斷各個數據的字節大小,在進行讀取,這樣就會浪費時間。爲了節省時間,會以下的方式去存儲數據:內存

  在存儲數據時,會對char a 補充 3 個字節,這樣在訪問 char a、int b 時,每次只需讀取 4 個字節就能夠,以一種空間換時間方式來提升效率。編譯器

  當如圖存放數據以後,整個結構體的大小爲 9 個字節。這與計算輸出的結果不符(還記得,經過程序計算的大小爲 12 個字節),這是爲何嗎??io

  還記得前面說的內存對齊的第四條規則嗎??

4.結構體總大小必須是對齊模數的整數倍。

  在上面給出了一個表格,上面有常見數據類型的模數,那咱們如何肯定一個結構提的模數呢???

  其實結構體的模數等於其內部模數最大的成員類型的模數

 struct AA { char a; int b; char c; };

  對於結構體AA來講,他的模數就是 4。

  則該結構體的大小必須是 4 的整數倍,因此在最後還會補充 3 個字節(以下圖)。

  這樣結構體AA的大小就是 12 個字節。


  在添加點難度:
#include <stdlib.h> #include <iostream> using namespace std; int main() { struct AA { char a; int b; char c; }; struct BB { char d; int e; double f; AA g; }; cout << sizeof(BB) << endl; system("pause"); }

  先來看看答案:

  來分析一下:

 

 

  到結構AA,來看看結構體AA的狀況:

  因此接下來應該以下圖:

  由圖可知 結構體BB一共佔據32個字節的內存,到這裏就完了嗎??

  還記得 內存對齊的第四條規則嗎??

4.結構體總大小必須是對齊模數的整數倍。

  結構體BB的模數爲多少呢??

  由於double e 的模數最大爲 8 ,因此BB的模數也爲8。32 是 8 的倍數,因此結構體BB只佔 32 個字節。



4、自定義模數大小

  能夠經過#pragma pack() 自定義模數的大小。

#include <stdlib.h> #include <iostream> using namespace std; #pragma pack(1) int main() { struct AA { char a; int b; char c; }; struct BB { char d; int e; double f; AA g; }; cout << sizeof(BB) << endl; system("pause"); }

  將模數的大小自定義爲 1 後,運行結果以下:

  當模數大小定義爲 2 時,運行結果以下:

  能夠本身去試試畫圖理解。

相關文章
相關標籤/搜索