C語言中結構體變數占用空間及位元組對齊問題

2022-06-14 12:57:08 字數 1452 閱讀 2543

**:

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

1 #include2

3 typedef struct

test

4test;910

int main(void)11

不妨大膽猜想,結構體所佔空間是不是其成員所佔空間的代數和呢??按照這個猜想,該題的答案應該為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個位元組。

再看這一題

1 #include2

3 typedef struct

test

4test;910

int main(void)11

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

其實記憶體對齊的規則和編譯環境也是有一定的關係,其預設對齊係數也有差異,並且也是可以通過預處理命令#pragma pack(n)來改變的。

C語言中結構體占用記憶體問題

之前對結構體占用記憶體一直很混亂,到底是按照哪個變數型別計算記憶體?還是怎麼計算?下面先看乙個例子 struct str1 str1這個結構體占用的記憶體是多少呢?如果用變數型別直接想加,得到的結果是17,但顯然不是這樣的。這個程式執行的正確結果是24.為什麼呢?因為為了cpu能夠快速訪問,提高訪問...

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

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

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

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