所謂的位元組對齊,就是各種類型的資料按照一定的規則在空間上排列,而不是順序的一個接一個的排放,這個就是對齊。我們經常聽說的對齊在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
本頁版權歸作者和部落格園所有,歡迎轉載,但未經作者同意必須保留此段聲明,
且在文章頁面明顯位置給出原文連結,否則保留追究法律責任的權利