結構體邊界對齊

2021-08-20 07:43:53 字數 1537 閱讀 3520

許多實際的計算機系統對基本型別資料在記憶體中存放的位置有限制,它們會要求這些資料的首位址的值是某個數k(通常它為4或8)的倍數,這就是所謂的記憶體對齊,而這個k則被稱為該資料型別的對齊模數(alignment modulus)。當一種型別s的對齊模數與另一種型別t的對齊模數的比值是大於1的整數,我們就稱型別s的對齊要求比t強(嚴格),而稱t比s弱(寬鬆)。這種強制的要求一來簡化了處理器與記憶體之間傳輸系統的設計,二來可以提公升讀取資料的速度。比如這麼一種處理器,它每次讀寫記憶體的時候都從某個8倍數的位址開始,一次讀出或寫入8個位元組的資料,假如軟體能保證double型別的資料都從8倍數字址開始,那麼讀或寫乙個double型別資料就只需要一次記憶體操作。否則,我們就可能需要兩次記憶體操作才能完成這個動作,因為資料或許恰好橫跨在兩個符合對齊要求的8位元組記憶體塊上。某些處理器在資料不滿足對齊要求的情況下可能會出錯,但是intel的ia32架構的處理器則不管資料是否對齊都能正確工作。不過intel奉勸大家,如果想提公升效能,那麼所有的程式資料都應該盡可能地對齊。

規則:

第一,編譯器按照成員列表的順序給每個成員分配記憶體.

第二,當成員需要滿足正確的邊界對齊時,成員之間用額外位元組填充.

第三,結構體的首位址必須滿足結構體中邊界要求最為嚴格的資料型別所要求的位址.

第四,結構體的大小為其最寬基本型別的整數倍.

sizeof操作符能夠得出乙個結構體的整體長度,包括因邊界對齊而額外填充的那些位元組.

offsetof(type, member)巨集能求得成員在結構體內的偏移,返回size_t.

例題:某c語言的程式段如下:

struct 

record;

record.a = 273;

若record變數的首位址為0xc008,則位址0xc008的內容以及record.c的位址分別為:

a. 0x00、0xc00d

b. 0x00、0xc00e

c. 0x11、0xc00d

d. 0x11、0xc00e

比如十六進製制數0x123456,則我們知道12是最高位,34其次,56最低。那麼儲存的時候,如果用的是小端序,記憶體位址最小的那個用來儲存56,位址增大一些存34,再高一些存12.

接著,重點在於對齊,結構體中會根據第乙個資料的大小進行對齊。

問題來了,我們是按照最大資料進行對齊還是按照第乙個資料進行對齊?

不同機器上的對齊策略不同,一般按照int的4個位元組進行對齊。

而這個結構體共7個位元組,所以對齊後是8個位元組。

那麼這個留空的位元組位置在哪?

就需要牽涉到變數起始位址的問題。

對於273,十六進製制是0x111,因此第乙個低位位元組儲存0x11,再高一點的位元組儲存0x01,後面兩個位元組為空的不管。好了,看儲存char b,這個大小是1個位元組,存完之後,如果緊接著就存short c,那麼c的起始位址是個奇數,不能被2整除。

因此在char b後留白乙個位元組。

結構體邊界對齊

許多實際的計算機系統對基本型別資料在記憶體中存放的位置有限制,它們會要求這些資料的首位址的值是某個數k 通常它為4或8 的倍數,這就是所謂的記憶體對齊,而這個k則被稱為該資料型別的對齊模數 alignment modulus 當一種型別s的對齊模數與另一種型別t的對齊模數的比值是大於1的整數,我們就...

整數邊界對齊方式 c中結構體邊界對齊

原則1 普通資料成員對齊規則 第乙個資料成員放在offset為0的地方,以後每個資料成員儲存的起始位置要從該成員大小的整數倍開始 比如int在32位機為 位元組,則要從4的整數倍位址開始儲存 原則2 結構體成員對齊規則 如果乙個結構裡有某些結構體成員,則該結構體成員要從其內部最大元素大小的整數倍位址...

結構體對齊

現在去掉第乙個成員變數為如下 pragma pack 4 class testc int nsize sizeof testc 按照正常的填充方式nsize的結果應該是8,為什麼結果顯示nsize為6呢?事實上,很多人對 pragma pack的理解是錯誤的。pragma pack規定的對齊長度,實...