一、概念
對齊跟資料在記憶體中的位置有關。如果乙個變數的記憶體位址正好位於它長度的整數倍,他就被稱做自然對齊。比如在32位cpu下,假設乙個整型變數的位址為0x00000004,那它就是自然對齊的。
二、為什麼要位元組對齊
在c語言中,結構是一種復合資料型別,其構成元素既可以是基本資料型別(如int、long、float等)的變數,也可以是一些復合資料型別(如陣列、結構、聯合等)的資料單元。在結構中,編譯器為結構的每個成員按其自然邊界(alignment)分配空間。各個成員按照它們被宣告的順序在記憶體中順序儲存,第乙個成員的位址和整個結構的位址相同。
為了使cpu能夠對變數進行快速的訪問,變數的起始位址應該具有某些特性,即所謂的」對齊」. 比如4位元組的int型,其起始位址應該位於4位元組的邊界上,即起始位址能夠被4整除.
需要位元組對齊的根本原因在於cpu訪問資料的效率問題。假設上面整型變數的位址不是自然對齊,比如為0x00000002,則cpu如果取它的值的話需要訪問兩次記憶體,第一次取從0x00000002-0x00000003的乙個short,第二次取從0x00000004-0x00000005的乙個short然後組合得到所要的資料,如果變數在0x00000003位址上的話則要訪問三次記憶體,第一次為char,第二次為short,第三次為char,然後組合得到整型資料。而如果變數在自然對齊位置上,則只要一次就可以取出資料。一些系統對對齊要求非常嚴格,比如sparc系統,如果取未對齊的資料會發生錯誤,舉個例:
char ch[8];
char *p = &ch[1];
int i = *(int *)p;
執行時會報segment error,而在x86上就不會出現錯誤,只是效率下降。
三、正確處理位元組對齊
對於標準資料型別,它的位址只要是它的長度的整數倍就行了,而非標準資料型別按下面的原則對齊:
陣列 :按照基本資料型別對齊,第乙個對齊了後面的自然也就對齊了。
聯合 :按其包含的長度最大的資料型別對齊。
結構體: 結構體中每個資料型別都要對齊。
比如有如下乙個結構體:
struct stu;
struct stu my_stu;
由於在x86下,gcc預設按4位元組對齊,它會在***後面跟name後面分別填充三個和兩個位元組使length和整個結構體對齊。於是我們sizeof(my_stu)會得到長度為20,而不是15.
四、更改c編譯器的預設位元組對齊方式
在預設情況下,c編譯器為每乙個變數或是資料單元按其自然對界條件分配空間。一般地,可以通過下面的方法來改變預設的對界條件:
· 使用偽指令#pragma pack (n),c編譯器將按照n個位元組對齊。
· 使用偽指令#pragma pack (),取消自定義位元組對齊方式。
另外,還有如下的一種方式:
· __attribute((aligned (n))),讓所作用的結構成員對齊在n位元組自然邊界上。如果結構中有成員的長度大於n,則按照最大成員的長度來對齊。
· __attribute__ ((packed)),取消結構在編譯過程中的優化對齊,按照實際占用位元組數進行對齊。
五、什麼時候需要設定對齊
在設計不同cpu下的通訊協議時,或者編寫硬體驅動程式時暫存器的結構這兩個地方都需要按一位元組對齊。即使看起來本來就自然對齊的也要使其對齊,以免不同的編譯器生成的**不一樣.
六、舉例說明
例1struct test
;由於編譯器預設情況下會對這個struct作自然邊界(有人說「自然對界」我覺得邊界更順口)對齊,結構的第乙個成員x1,其偏移位址為0,佔據了第1個位元組。第二個成員x2為short型別,其起始位址必須2位元組對界,因此,編譯器在x2和x1之間填充了乙個空位元組。結構的第三個成員x3和第四個成員x4恰好落在其自然邊界位址上,在它們前面不需要額外的填充位元組。在test結構中,成員x3要求4位元組對界,是該結構所有成員中要求的最大邊界單元,因而test結構的自然對界條件為4位元組,編譯器在成員x4後面填充了3個空位元組。整個結構所佔據空間為12位元組。
例2#pragma pack(1) //讓編譯器對這個結構作1位元組對齊
struct test
;#pragma pack() //取消1位元組對齊,恢復為預設4位元組對齊
這時候sizeof(struct test)的值為8。
例3#define gnuc_packed __attribute__((packed))
struct packed test
gnuc_packed;
這時候sizeof(struct test)的值仍為8。
c語言位元組對齊
現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特 定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。基本資料型別自身對齊,也叫自然對齊。就是說...
C語言位元組對齊
一 概念 對齊跟資料在記憶體中的位置有關。如果乙個變數的記憶體位址正好位於它長度的整數倍,他就被稱做自然對齊。比如在32位cpu下,假設乙個整型變數的位址為0x00000004,那它就是自然對齊的。二 為什麼要位元組對齊 需要位元組對齊的根本原因在於cpu訪問資料的效率問題。假設上面整型變數的位址不...
C語言位元組對齊
1.什麼是對齊?現代計算機中記憶體空間都是按照位元組 byte 劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定變數的時候經常在特定的記憶體位址訪問,這就需要各型別資料按照一定的規則在空間上排列,而不是順序地乙個接乙個地排放,這就是對齊。2.計算機為什麼要對齊?...