天天看點

詳解4位元組對齊

所謂的位元組對齊,就是各種類型的資料按照一定的規則在空間上排列,而不是順序的一個接一個的排放,這個就是對齊。我們經常聽說的對齊在N上,它的含義就是資料的存放起始位址%N==0。具體對齊規則會在下面的篇幅中介紹。首先還是讓我們來看一下,為什麼要進行位元組對齊吧。

view plaincopy to clipboardprint?

01.struct A {  

02.    char c;  

03.    int i;  

04.};  

05.struct A a;  

Code 13-1

假設變量a存放在記憶體中的起始位址為0x00,那麼其成員變量c的起始位址為0x00,成員變量i的起始位址為0x01,變量a一共占用了5個位元組。當CPU要對成員變量c進行通路時,隻需要一個讀周期即可。而如若要對成員變量i進行通路,那麼情況就變得有點複雜了,首先CPU用了一個讀周期,從0x00處讀取了4個位元組(注意由于是32位架構),然後将0x01-0x03的3個位元組暫存,接着又花費了一個讀周期讀取了從0x04-0x07的4位元組資料,将0x04這個位元組與剛剛暫存的3個位元組進行拼接進而讀取到成員變量i的值。為了讀取這個成員變量i,CPU花費了整整2個讀周期。試想一下,如果資料成員i的起始位址被放在了0x04處,那麼讀取其所花費的周期就變成了1,顯然引入位元組對齊可以避免讀取效率的下降,但這同時也浪費了3個位元組的空間(0x01-0x03)。

有了上述的基本概念之後,讓我們來看一下,編譯器是按照什麼樣的原則進行對齊的。首先有3個重要的概念:自身對齊值,指定對齊值和有效對齊值。

自身對齊值:即資料類型的自身的對齊值。例如char型的資料,其自身對齊值為1位元組;short型的資料,其自身對齊值為2位元組;int,float,long類型,其自身對齊值為4位元組;double類型,其自身對齊值為4位元組;而struct和class類型的資料其自身對齊值為其成員變量中自身對齊值最大的那個值。

指定對齊值:#pragma pack (value)時指定的對齊值value

有效對齊值:上述兩個對齊值中最小的那個。

我們一般說的對齊在N上,都是指有效對齊在N上。說了這麼多,還是讓我們先來看一些例子來加深對這些概念的了解吧。例:假設在x86機器上,假設編譯器按預設4位元組進行對齊

04.    short s;  

05.};  

06.  

07.#pragma pack (2)   /* 指定按2位元組對齊 */  

08.struct B {  

09.    char c;  

10.    short s;  

11.    int i;  

12.};  

13.#pragma pack ()    /* 恢複預設對齊 */  

Code 13-2

接下來讓我們考察sizeof(struct B)的結果。這裡需要注意的是,在B被聲明前,指定對齊值已經被設定為2個位元組。資料成員c的有效對齊值為1,存放起址0x00,s的有效對齊值為2,存放起址0x02,i的有效對齊值也為2,存放起址為0x04,累加起來一共是8個位元組,已經是資料結構B的有效對齊值2的整數倍了。是以sizeof(struct B)的結果8個位元組。

看到這裡,應該對位元組對齊有了一定的了解了吧。接下來我們要看一個更加複雜的例子:假設在x86機器上,假設編譯器按預設4位元組進行對齊 

01.#pragma pack(8)  

02.struct S1 {  

03.    char a;  

04.    long b;  

07.struct S2 {  

08.    char c;  

09.    struct S1 d;  

10.    long long e;  

11.};  

12.#pragma pack()  

13.   

Code 13-3

運用上面所學到的知識,應該不難得出sizeof(struct S1)的值為8位元組,其中a的有效對齊值為1,b的有效對齊值為4,結構S1的有效對齊值為4。現在讓我們來看看sizeof(struct S2)的值會是多少呢?首先成員c的有效對齊值為1,S1的自身對齊值為成員的最大自身對齊值,即4位元組,其指定對齊值為8,則其有效對齊值也為4,存放起址應該為0x04,并且占用8個位元組(0x04+0x08=0x0C),其中0x01-0x03被用來填充。接下去資料成員e的有效對齊值為4,存放起址應該是0x0D % 8 == 0,占用8個位元組(0x10)。最後考察S2本身的有效對齊值應該是4位元組,而0x0D%8==0,就不需要填充了,是以sizeof(struct S2)=20。

在vc6工具中,我們可以選擇[project]->[Settings]->[C/C++]->[Code Generation]->[Struct member alignment]來更改預設對齊位元組數。

QQ:519841366

本頁版權歸作者和部落格園所有,歡迎轉載,但未經作者同意必須保留此段聲明,

且在文章頁面明顯位置給出原文連結,否則保留追究法律責任的權利

繼續閱讀