C語言中結構體變數到底占多大空間

2021-08-27 11:48:41 字數 1660 閱讀 2079

很久之前就想將記憶體對齊這塊兒知識點總結記錄下來,無奈本人患有very very嚴重的拖拉症,直到今天才下決心將這件事兒解決掉,廢話不多說了,開工!(ps:本人所用編譯器version為 gcc ubuntu4.9.2-10 ubuntu13 4.9.2)

結構體到底占多大的空間呢?先看一下下面這道題的輸出結果:

#includetypedef struct test

test;

int main(void)

不妨大膽猜想,結構體所佔空間是不是其成員所佔空間的代數和呢??按照這個猜想,該題的答案應該為13,然而事實卻讓人大跌眼鏡,本題輸出的結果為16。google一下知這是因為計算機中存在一種叫做記憶體對齊的機制導致了該結果的發生。

在計算機中通常會讓cpu從記憶體中一次讀取若干個位元組的資料,而不是一次只讀取乙個位元組的資料,這樣的好處是提高了計算機的效率,然而壞處也顯而易見。

假設cpu一次從記憶體中讀取四個位元組的資料,而現在記憶體中存在乙個char型的資料和乙個int型的資料,如果記憶體不對齊,當cpu第一次跨越四個位元組定址找到了乙個char型的資料,而此時cpu的指向到了int型的中間區域,導致這個int型變數未找到,然後cpu會返回去再次尋找,直到找到該int型變數。這樣不但沒能提高效率,反而增加了cpu的負擔。因此我們通常會在第乙個char型變數後邊填充一部分資料來保證每次定址時位址都是該資料的整數倍,這樣就避免了上述「錯誤」的發生,也就是所謂的記憶體對齊。

記憶體對齊的規則很簡單:

一、起始位置為成員資料型別所佔記憶體的整數倍,若不足則不足部分用資料將記憶體填充為該資料型別的整數倍。

二、結構體所佔總記憶體為其成員變數中所佔空間最大資料型別的整數倍。

假設上題中結構體變數是從零號記憶體開始儲存,則char型變數佔乙個位元組,而後int型變數發現起始位置在一號記憶體處,並不滿足起始位置為int型所佔4位元組整數倍的要求,故將一二三號記憶體填充滿,從四號記憶體處開始儲存該int型成員,當該int型成員儲存完成後已經用了八個位元組的空間,因此此時double型成員的起始位置為第八號記憶體,滿足第一條條件,所以double型開始儲存,儲存完成後該結構體變數剛好佔16個位元組,剛好是最大資料型別double八個位元組的整數倍,所以儲存完成,因此該結構體變數佔了16個位元組。

再看這一題

#includetypedef struct test

test;

int main(void)

這題乍一看和上一題的區別僅僅是將int型和double型調換了位置,那結果呢?結果肯定是不一樣的,按照上述分析步驟走一遍看看,先是char型從零號開始儲存,因為要遵循第一條原則故double型從八號開始儲存,一到七号被填充,double型儲存完後int型從16號位置開始儲存,儲存完成後發現此時一共佔了20個位元組的空間,不滿足第二條規則,因此又將20到23號位置填充,所以該結構體變數佔24個位元組,從這裡就可以看出在定義結構體時成員變數的順序會影響其在記憶體中所佔的資源大小,因此我們在定義結構體時要調整順序使其盡可能在記憶體中所佔空間最小。

其實記憶體對齊的規則和編譯環境也是有一定的關係,其預設對齊係數也有差異,並且也是可以通過預處理命令#pragma pack(n)來改變的,這裡所說的規則只是乙個常見規則,不過話說回來萬變不離其宗,其實本質都是一樣的

C語言中結構體變數到底占多大空間

很久之前就想將記憶體對齊這塊兒知識點總結記錄下來,無奈本人患有very very嚴重的拖拉症,直到今天才下決心將這件事兒解決掉,廢話不多說了,開工!ps 本人所用編譯器version為 gcc ubuntu4.9.2 10 ubuntu13 4.9.2 結構體到底占多大的空間呢?先看一下下面這道題的...

C語言中結構體

struct oursvoid main struct ours o2 01 結構體整體直接賦值的時候,即使字串也可以直接賦值 o1.str o2.str 錯誤,字串不能直接賦值 字串拷貝的方式 sprintf o1.str,02.str strcpy o1.str,o2.str 3.1 第一種情況...

c語言中結構體型別變數型別,結構體變數名賦值

結構體的詳情參考本文件 這幾天看圖用領接表儲存圖時候,開始實現的時候發現對結構體的變數名賦值有些疑惑,疑惑的地方查了下,留做備份 此宣告宣告了擁有3個成員的結構體,分別為整型的a,字元型的b和雙精度的c 同時又宣告了結構體變數s1 這個結構體並沒有標明其標籤 struct s1 此宣告宣告了擁有3個...