共用體和結構體所佔記憶體大小的計算方法二

2021-08-03 13:54:41 字數 2711 閱讀 9196

乙個結構體變數定義完之後,其在記憶體中的儲存並不等於其所包含元素的寬度之和。

例一:

#include 

using

namespace

std;

struct x

s1;void main()

比如例一中的結構體變數s1定義之後,經測試,會發現sizeof(s1)= 16,其值不等於sizeof(s1.a) = 1、sizeof(s1.b) = 4和 sizeof(s1.c) = 8三者之和,這裡面就存在儲存對齊問題。

原則一:結構體中元素是按照定義順序乙個乙個放到記憶體中去的,但並不是緊密排列的。從結構體儲存的首位址開始,每乙個元素放置到記憶體中時,它都會認為記憶體是以它自己的大小來劃分的,因此元素放置的位置一定會在自己寬度的整數倍上開始(以結構體變數首位址為0計算)。

比如此例,首先系統會將字元型變數a存入第0個位元組(相對位址,指記憶體開闢的首位址);然後在存放整形變數b時,會以4個位元組為單位進行儲存,由於第乙個四位元組模組已有資料,因此它會存入第二個四位元組模組,也就是存入到4~8位元組;同理,存放雙精度實型變數c時,由於其寬度為8,其存放時會以8個位元組為單位儲存,也就是會找到第乙個空的且是8的整數倍的位置開始儲存,此例中,此例中,由於頭乙個8位元組模組已被占用,所以將c存入第二個8位元組模組。整體儲存示意圖如圖1所示。

考慮另外乙個例項。

例二:

struct x

s2;

在例二中僅僅是將double型的變數和int型的變數互換了位置。測試程式不變,測試結果卻截然不同,sizeof(s2)=24,不同於我們按照原則一計算出的8+8+4=20,這就引出了我們的第二原則。

原則二:在經過第一原則分析後,檢查計算出的儲存單元是否為所有元素中最寬的元素的長度的整數倍,是,則結束;若不是,則補齊為它的整數倍。

例二中,我們分析完後的儲存長度為20位元組,不是最寬元素長度8的整數倍,因此將它補齊到8的整數倍,也就是24。這樣就沒問題了。其儲存示意圖如圖2所示。

掌握了這兩個原則,就能夠分析所有資料儲存對齊問題了。再來看幾個例子,應用以上兩個原則來判斷。

例三:

struct x

s3;

首先根據原則一來分析。按照定義的順序,先儲存double型的a,儲存在第0~7個位元組;其次是char型的b,儲存在第8個位元組;接下來是int型的c,順序檢查後發現前面三個四位元組模組都被占用,因此儲存在第4個四位元組模組,也就是第12~15位元組。按照第一原則分析得到16個位元組,16正好是最寬元素a的寬度8的整數倍,因此結構體變數s3所佔儲存空間就是16個位元組。儲存結構如圖3所示。
例四:

struct x

s4;

仍然首先按照第一原則分析,得到的位元組數為8+4+4+1=17;再按照第二原則補齊,則結構體變數s4所佔儲存空間為24。儲存結構如圖4所示:
例五:

struct x

s5;

同樣結合原則一和原則二分析,可知在s4的基礎上在結構體內部變數定義最後加入乙個int型變數後,結構體所佔空間並未增加,仍為24。儲存結構示意圖如圖5所示。
例六:

如果將例五中加入的變數e放到第乙個定義的位置,則情況就不同了。結構體所佔儲存空間會變為32。其儲存結構示意圖如圖6所示。

struct x

s6;

補充:前面所介紹的都是元素為基本資料型別的結構體,那麼含有指標、陣列或是其它結構體變數或聯合體變數時該如何呢?

1.包含指標型別的情況。只要記住指標本身所佔的儲存空間是4個位元組就行了,而不必看它是指向什麼型別的指標。

例七:

struct x              struct y               struct z

; };

};

經測試,可知sizeof(x)、sizeof(y)和sizeof(z)的值都為4。

2.含有構造資料型別(陣列、結構體和聯合體)的情況。首先要明確的是計算儲存空間時要把構造體看作乙個整體來為其開闢儲存空間;其次要明確的是在最後補齊時是按照所有元素中的基本資料型別元素的最長寬度來補齊的,也就是說雖然要把構造體看作整體,但在補齊的時候並不會按照所含結構體所佔儲存空間的長度來補齊的(即使它可能是最長的)。

例八:

struct x

;struct y

;

經測試,可知sizeof(x)為16,sizeof(y)為24。即計算y的儲存長度時,在存放第二個元素b時的初始位置是在double型的長度8的整數倍處,而非16的整數倍處,即系統為b所分配的儲存空間是第8~23個位元組。

如果將y的兩個元素char型的a和x型的b調換定義順序,則系統為b分配的儲存位置是第0~15個位元組,為a分配的是第16個位元組,加起來一共17個位元組,不是最長基本型別double所佔寬度8的整數倍,因此要補齊到8的整數倍,即24。測試後可得sizeof(y)的值為24。

由於結構體所佔空間與其內部元素的型別有關,而且與不同型別元素的排列有關,因此在定義結構體時,在元素型別及數量確定之後,我們還應該注意一下其內部元素的定義順序。

共用體和結構體所佔記憶體大小的計算方法一

共用體所佔記憶體大小 共用體所佔記憶體的大小即公用體中長度最大元素所占用的位元組數。方法一 結構體的記憶體大小 最後乙個成員的偏移量 最後乙個成員的大小 末尾的填充位元組數 例.1 struct data 比如說這個成員a,由於a是第乙個成員,所以它的位址就是結構體的首地 址,它相對於結構體的首位址...

共用體Union的記憶體大小

下例表示宣告乙個共用體foo union foo int i char c double k 再用已宣告的共用體可定義共用體變數。例如用上面說明的共用體定義乙個名為bar的共用體變數,可寫成 union foo bar 在共用體變數bar中,整型變數i和字元變數c共用同一記憶體位置。當乙個共用體被宣...

結構體和共用體的記憶體對齊

編譯器按照成員列表的順序乙個接乙個地給每個成員分配記憶體。只有當儲存成員時需要滿足正確的邊界對齊要求時,成員時間才可能出現用於填充的額外記憶體空間。系統禁止編譯器在乙個結構的起始位置跳過幾個位元組來滿足邊界對齊要求,因此所有結構的起始位置必須是結構中邊界要求最嚴格的資料所要求的位置。這段話來自 c和...