結構體對齊規則

2021-06-18 16:30:30 字數 2419 閱讀 4112

結構體對齊 , #pragma pack(4),結構體的長度(sizeof)

(乙個沒有考慮周詳的位段結構體中,可能存在大量「縫隙」)

1.實際對齊值決定系統一次劃分記憶體的位元組數量。系統為變數分配記憶體時,必須先劃分夠變數資料型別需要的對齊空間(對齊模數,位元組單位)。

2.       結構體的實際對齊值為結構體中最大的資料型別的長度a與系統規定的對齊值b兩者中間較小的那個值min(a,b)決定。如果變數的資料型別長度大於實際對齊值,為這個變數分配對齊空間時,系統連續進行多次分配以滿足對齊空間的要求。

3.       完全容納概念:

1.1   寬度比對齊空間小的變數不能分散在多個對齊空間中(注意:是對齊空間,不是位元組),如果前乙個對齊空間剩餘的大小不足以容納當前變數,則當前變數從下乙個對齊空間開始,前乙個對齊中間的不足部分,由系統自動填充(padding)。

1.2   如果變數的寬度大於對齊空間的寬度(即全域性對齊空間pack定義小於結構體中最大寬度的變數大小),則該變數的位址相對於結構體首位址的偏移量,必須是對齊空間大小的整數倍,即寬度大於對齊空間的變數,其記憶體分配不能從乙個對齊空間的中間開始,必須從乙個對齊空間的頭開始。例:

_tags的大小為16,而不是12或者其它,因為對齊空間大小是8(位元組),s1雖然只佔了1個位元組,但是剩下的7位元組不夠容納s2的8個位元組,所以s2必須從新的對齊空間開始分配。(上例中,如果pack為4,則_tags的大小則為12;如果pack為2,則_tags的大小則為10;如果pack為1,則_tags的大小則為9)

1.3   位段變數可以跨越位元組,但是不能跨越對齊空間。例如:

s2結構體中的位段和為64,剛好為8個位元組,但是sizeof(s2)值並不是8,而是12,這就是因為變數受到對齊空間約束的原因:變數不能跨越對齊空間。由於第乙個對齊間空間不能同時容納a,b,所以第乙個對齊空間中並沒有b的一部分內容,b從第二個對齊空間開始佔位,b,c一共占用了第二個對齊空間,第二個對齊空間中只剩下2位空位,不能容納d,所以d再分配乙個對齊空間4位元組。(此結構體因為所有變數資料型別相同,所以對齊值由結構體中的資料型別決定)。最後的結果是:第乙個對齊空間中空餘1位,第二個對齊空間中空餘2位,第三個對齊空間中空餘29位。

4.       共用對齊空間:當乙個對齊空間中可以容納幾個變數時,這些變數可以共用對齊空間。任何變數都不能跨越對齊空間

ø  如果乙個對齊空間足夠容納多個資料型別(注意:不是位段),則允許乙個對齊空間中存在不同資料型別的變數,否則,要開闢新的對齊空間。例如:(實際對齊值為4)

不同資料型別的a,b共用乙個對齊空間,因為變數不能跨越對齊空間,所以c獨佔乙個對齊空間,d獨佔乙個對齊空間,結構體長度值為12。

ø  使用位段時,有且只有相同資料型別的位段變數可以共用記憶體位元組!如果資料型別不相同,即使前乙個變數中剩餘的位空間完全可以容納後面幾個位段變數,下乙個變數的位空間分配也是從下乙個位元組開始分配,如果本對齊空間裡的剩餘位元組數能夠容納下乙個變數的資料型別(注意:是資料型別,不是變數位段數),則下乙個變數和本變數共用乙個對齊空間;否則,下乙個變數從乙個新的對齊空間開始。

例子:(因為系統對齊值8大於結構體中最大資料型別的長度4=sizeof(__int32),所以實際對齊值為4,而不是明確指定的8。)

a,b共用乙個對齊空間,c獨點乙個對齊空間,雖然第二個對齊空間的剩餘位段數8=32-24還完全可以容納d的位段數4,但是由於c,d的資料型別不一樣,所以d從下乙個位元組開始分配。由於c的資料型別(__int32)完全佔據乙個對齊空間,下乙個位元組是從新的對齊空間開始的,所以d從乙個新的對齊空間開始占用。所以sizeof(s1)的值為12。

如果例子改為:

由a,b共同佔乙個對齊空間,第乙個對齊空間被a,b的資料型別佔據,c從乙個新的對齊空間開始占用,實際對齊值為4,所以第二個對齊空間大小為4位元組,被c的資料型別占用兩位元組後,還剩下的兩位元組能夠完全容納d的資料型別(__int8),所以d的資料型別雖然和c的資料型別不一樣,但是d也不必從新的對齊空間開始占用,而是和c共用乙個對齊空間。所以sizeof的值為8,比上面的例子少使用乙個對齊空間。

一點引用:

1) 結構體變數的首位址能夠被其最寬基本型別成員的大小所整除;

2) 結構體每個成員相對於結構體首位址的偏移量(offset)都是成員大小的整數倍,如有需要編譯器會在成員之間加上填充位元組(internaladding);

3) 結構體的總大小為結構體最寬基本型別成員大小的整數倍,如有需要,編譯器會在最末乙個成員之後加上填充位元組(trailingpadding)。

類的記憶體分布對齊規則與結構體的類似,只是缺少了字段概念。

其一,c++語言保證「出現在derived class中的base class suboject有其完整性」;

其二,derivedclass的對齊數 = min(指定的全域性對齊數,max(base class的對齊數,derived class的對齊數))

可參見:

結構體對齊規則

結構體對齊規則 1 第乙個成員在與結構體變數偏移量為0處 2 其他成員變數需要對齊到某個數字 對齊數 的整數倍的位址處 對齊數 編譯器預設的乙個對齊數與該成員大小的較小值 vs中預設為8 3 結構體總大小為最大對齊數 每個成員變數除了第乙個成員都有乙個對齊數 的整數倍 4 如果巢狀了結構體的情況,巢...

結構體對齊規則

結構體預設的位元組對齊一般滿足三個準則 1 結構體變數的首位址能夠被其最寬基本型別成員的大小所整除 2 結構體每個成員相對於結構體首位址的偏移量 offset 都是成員自身大小的整數倍,如有需要編譯器會在成員之間加上填充位元組 internal adding 每乙個元素放置到記憶體中時,它都會認為記...

結構體對齊規則

1 資料成員對齊規則 結構或聯合的資料成員,第乙個資料成員放在offset為0的地方,以後每個資料成員的對齊按照 pragma pack指定的數值和這個資料成員自身長度中,比較小的那個進行。2 結構或聯合的整體對齊規則 在資料成員完成各自對齊後,結構或聯合本身也要進行對齊,對齊將按照 pragma ...