一、概念
對齊跟資料在記憶體中的位置有關。如果乙個變數的記憶體位址正好位於它長度的整數倍,他就被稱做自然對齊。比如在32位cpu下,假設乙個整型變數的位址為0x00000004,那它就是自然對齊的。
二、為什麼要位元組對齊
需要位元組對齊的根本原因在於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.
四、__attribute__選項
我們可以按照自己設定的對齊大小來編譯程式,gnu使用__attribute__選項來設定,比如我們想讓剛才的結構按一位元組對齊,我們可以這樣定義結構體
struct stu__attribute__ ((aligned (1)));
struct stu my_stu;
則sizeof(my_stu)可以得到大小為15。
上面的定義等同於
struct stu__attribute__ ((packed));
struct stu my_stu;
__attribute__((packed))得變數或者結構體成員使用最小的對齊方式,即對變數是一位元組對齊,對域(field)是位對齊.
五、什麼時候需要設定對齊
在設計不同cpu下的通訊協議時,或者編寫硬體驅動程式時暫存器的結構這兩個地方都需要按一位元組對齊。即使看起來本來就自然對齊的也要使其對齊,以免不同的編譯器生成的**不一樣.
c語言位元組對齊
現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特 定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。基本資料型別自身對齊,也叫自然對齊。就是說...
C語言位元組對齊
一 概念 對齊跟資料在記憶體中的位置有關。如果乙個變數的記憶體位址正好位於它長度的整數倍,他就被稱做自然對齊。比如在32位cpu下,假設乙個整型變數的位址為0x00000004,那它就是自然對齊的。二 為什麼要位元組對齊 在c語言中,結構是一種復合資料型別,其構成元素既可以是基本資料型別 如int ...
C語言位元組對齊
1.什麼是對齊?現代計算機中記憶體空間都是按照位元組 byte 劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定變數的時候經常在特定的記憶體位址訪問,這就需要各型別資料按照一定的規則在空間上排列,而不是順序地乙個接乙個地排放,這就是對齊。2.計算機為什麼要對齊?...