一、什么是內存對齊

       現(xiàn)代計算機中內存空間都是按照byte劃分的,從理論上講似乎對任何類型的變量的訪問可以從任何地址開始,但實際情況是在訪問特定變量的時候經(jīng)常在特定的內存地址訪問,這就需要各類型數(shù)據(jù)按照一定的規(guī)則在空間上排列,而不是順序的一個接一個的排放,這就是對齊。

       為什么要了解內存對齊:各個硬件平臺對存儲空間的處理上有很大的不同。一些平臺對某些特定類型的數(shù)據(jù)只能從某些特定地址開始存取。其他平臺可能沒有這種情況,但是最常見的是如果不按照適合其平臺要求對數(shù)據(jù)存放進行對齊,會在存取效率上帶來損失。比如有些平臺每次讀都是從偶地址開始,如果一個int型(假設為32位系統(tǒng))如果存放在偶地址開始的地方,那么一個讀周期就可以讀出,而如果存放在奇地址開始的地方,就可能會需要2個讀周期,并對兩次讀出的結果的高低字節(jié)進行拼湊才能得到該int數(shù)據(jù)。顯然在讀取效率上下降很多。這也是空間和時間的博弈。

  通常我們不需要去主動進行內存對齊的操作,編譯器會自動為我們選擇最優(yōu)的對齊規(guī)則方式,合理利用空間節(jié)省程序運行的時間,但若是我們能了解這種規(guī)則,對于我們編寫程序還是會有很大的幫助的。

二、對齊內存規(guī)則

  1.第一個成員在與結構體變量偏移量為0的地址處。

  2.其他成員變量要對齊到對齊數(shù)(編譯器默認的一個對齊數(shù)與該成員大小的較小值)的整數(shù)倍的地址處。

  3.結構體總大小為最大對齊數(shù)(除了第一個成員每個成員變量都有一個對齊數(shù))的整數(shù)倍。

  4.如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數(shù)的整數(shù)倍處,結構體的整體大小就是所有最大對齊數(shù)(含嵌套結構體的對齊數(shù))的整數(shù)倍。

 

三、實例解釋

 

要想要看出數(shù)據(jù)的對齊方式,首先你就得明白各種數(shù)據(jù)類型在各種操作系統(tǒng)下所占字節(jié)的大小。

我們來看一下在32位系統(tǒng)下各種參數(shù)類型所占字節(jié)的大?。?/p>

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

接著我們用幾個例子來講解對齊規(guī)則:

(1)

首先我們用一字節(jié)對齊的方式來檢驗我們之前所說的類型所占字節(jié)大小:

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

 1 #pragma pack(1)//讓編譯器對此結構體作字節(jié)對齊 2 struct A 3 { 4         char a;//  1 5         int b;//   4 6         short c;// 2 7         long d;//  4 8         float e;// 4 9 };10 #pragma pack()//取消字節(jié)對齊,回復默認字節(jié)對齊11 int main()12 {13         struct A a;14         printf("%d\n",sizeof(a));15         return 0;16 }

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

如果沒有字節(jié)對齊(或者為一字節(jié)對齊方式),按照我們之前的計算方式,1+4+2+4+4=15,所占字節(jié)大小應該為15。

程序運行:

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

 

(2)我們取消之前的設置,直接使用默認對齊數(shù)對齊。

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

 1 #include <stdio.h> 2 //#pragma pack(1)//讓編譯器對此結構體作字節(jié)對齊 3 struct A 4 { 5         char a;//  1 6         int b;//   4 7         short c;// 2 8         long d;//  4 9         float e;// 410 };11 //#pragma pack()//取消字節(jié)對齊,回復默認字節(jié)對齊12 int main()13 {14         struct A a;15         printf("%d\n",sizeof(a));16         return 0;17 }

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

程序運行:

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

由上圖可以看到,明明是一樣的程序,只不過取消了1字節(jié)對齊,就由原來的占15字節(jié)變成了占20字節(jié),這就是字節(jié)對齊的原因。

我們用一張圖來解釋:

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

  第一個成員char一開始占用的是0偏移處,占用一個字節(jié)位,但由于是4字節(jié)對齊,且第二個成員int占用的字節(jié)位4,在4字節(jié)對齊的規(guī)則下,char后面只有三個字節(jié)空位,不足以放下,所以在三偏移處另開一個空存放,第三個成員short占用2字節(jié),可以放入,第四個成員long和第五個成員float依照前面的規(guī)則正好存放20個字節(jié),20個字節(jié)正好為這個結構體的最大對齊數(shù)的整數(shù)倍,所以這個結構體占用空間為20字節(jié)。

 

(3)前面我們說的都是剛好的情況,有些朋友可能還是不能很好的理解這個規(guī)則,我們再舉幾個例子:

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

 1 #include <stdio.h> 2 //#pragma pack(1)//讓編譯器對此結構體作字節(jié)對齊 3 struct A 4 { 5         char a;//  1 6         int b;//   4 7         short c;// 2 8         //long d;//  4 9         //float e;// 410 };11 //#pragma pack()//取消字節(jié)對齊,回復默認字節(jié)對齊12 int main()13 {14         struct A a;15         printf("%d\n",sizeof(a));16         return 0;17 }

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

程序運行:

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

  char、int、short按一字節(jié)方式為7,但是結構體對齊之后為12,按照我們在(2)中將的方式:char占0偏移處,一字節(jié);int在插入之后放不下,所以另起一個整數(shù)倍空間,在3偏移處,占4字節(jié);short在7偏移處,占2字節(jié)??偣舱?0字節(jié),但按照我們之前講的,整個結構體的大小應該為最大偏移數(shù)的整數(shù)倍,所以最小整數(shù)倍應該為12,所以整個結構體占12字節(jié)。

 

(4)如果不信,我們可以在來變化一下結構體內數(shù)據(jù)驗證

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

 1 #include <stdio.h> 2 //#pragma pack(1)//讓編譯器對此結構體作字節(jié)對齊 3 struct A 4 { 5         char a;//  1 6         //int b;//   4 7         short c;// 2 8         long d;//  4 9         char g;//  110         //float e;// 411 };12 //#pragma pack()//取消字節(jié)對齊,回復默認字節(jié)對齊13 int main()14 {15         struct A a;16         printf("%d\n",sizeof(a));17         return 0;18 }

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

程序運行:

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

  char在0偏移處,占一字節(jié),short為2字節(jié),在最大偏移數(shù)的范圍內能存下,所以在1偏移處占2字節(jié),long在3偏移處占4字節(jié),char在7偏移處占1字節(jié),總共占9字節(jié),按照對齊規(guī)則,總大小應該為4的整數(shù)倍,所以總大小為12。

 

 

四、對齊原因

  1.平臺原因(移植原因):不是所有的硬件平臺都能訪問任意地址上的任意數(shù)據(jù)的;某些硬件平臺只能在某些地址處取某些特定類型的數(shù)據(jù),否則拋出硬件異常。

  2.性能原因:數(shù)據(jù)結構(尤其是棧)應該盡可能地訪問在自然邊界上對齊。原因在于,為了訪問未對齊的內存,處理器需要作兩次內存訪問;而對齊的內存訪問僅需要一次訪問。

 

五、內存對齊的好處

你知道了內存對齊的規(guī)則那么我們在編寫程序的時候就能編寫出更加有效高效的程序。

用一個例子來簡單的解釋一下:

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

 1 #include <stdio.h> 2  3 struct A 4 { 5         char a; 6         int b; 7         short c; 8 }; 9 struct B10 {11         char a;12         short b;13         int c;14 };15 int main()16 {17         struct A a;18         struct B b;19         printf("%d\n",sizeof(a));20         printf("%d\n",sizeof(b));21         return 0;22 }

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

程序運行:

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

結構體內成員都一樣但是排列方式不一樣,結構體的占用空間不一樣。

用兩張圖就可以簡單解釋:

電腦培訓,計算機培訓,平面設計培訓,網(wǎng)頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

http://www.cnblogs.com/hdcsywy/p/7182315.html

延伸閱讀

內存對齊小解-Java培訓,做最負責任的教育,學習改變命運,軟件學習,再就業(yè),大學生如何就業(yè),幫大學生找到好工作,lphotoshop培訓,電腦培訓,電腦維修培訓,移動軟件開發(fā)培訓,網(wǎng)站設計培訓,網(wǎng)站建設培訓內存對齊小解