字節對齊

       計算機的內存空間都是按照字節來劃分的,從理論上講,對任何類型的變量的訪問可以從任何地址開始,但實際情況是在訪問特定變量的時候經常在特定的內存地址訪問,這就需要各類型的數據按照一定的規則在空間上排列,而不是順序的一個接着一個排列,這就是內存對齊。

       內存對齊是爲了提高CPU對數據的訪問速度(特別是在棧中)。對於對齊的內存地址,處理器僅需一次就可以訪問到,而對於未對齊的內存地址,處理器需要訪問兩次。

       我們寫程序時不需要去指定對齊方式,編譯器會去自動對齊,同樣,我們可以自己指定對齊值。由於編譯器有自動對齊的機制,所以一般我們是不需要考慮對齊的。對於內存對齊問題,最常見的就是struct結構體的sizeof的結果。下面通過例子介紹一下內存對齊問題。

       char類型佔一個字節,所以起始的偏移地址按1對齊(即起始偏移地址%1=0);int類型佔四個字節,所以起始偏移地址按4對齊(即起始偏移地址%4=0);short類型佔2個字節,所以起始偏移地址%2=0);double佔8個字節,所以起始偏移地址按8對齊(即起始偏移地址%8=0);同時,結構體自身也要考慮對齊,即結構體所佔空間總和爲這個對齊值的整數倍。

       (偏移地址%N=0,其中N取自身對齊值和指定對齊值裏較小的值,VC6默認對齊值爲8。以上幾個對齊值是各個類型數據的自身對齊值。而結構體的對齊值爲結構體成員裏對齊值得最大值和指定對齊值兩者裏取較小值)

struct test1 {     char a;     int b;     short c; };

       假設地址是從0x1000開始的,char類型對齊值爲1,0x1000%1=0,所以存放地址符合要求;int類型的對齊值爲4,所以起始地址要從0x1004開始到0x1007這四個字節來存放,0x1004%4=0;short對齊值爲2,起始地址0x1008%2=0,符合要求;再考慮結構體自身的對齊值,結構體自身的對齊值爲4,0x1000~0x1009爲10B,12%4=0,所以0x100A和0x100B也爲這個結構體所佔用,總共12個字節,因此,sizeof(test1)=12。

       同理,下面的例子sizeof的結果分別爲8和12.


  1. struct test2 

  2.     char a; 

  3.     char b; 

  4.     int c; 

  5. }; 


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

       如果需要人工指定對齊值,則使用以下命令:

       #pragma pack(val);      /*val爲對齊值,VC6默認8字節對齊*/

       #pragma pack();         /*取消指定對齊值,恢復默認對齊值*/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章