初學者對於結構體內存對齊與補齊的理解

2021-07-11 13:46:24 字數 2070 閱讀 3989

1、問題提出:

剛開始學習結構體的時候,我們通常認為結構體

struct number_1

st1;

占用空間為sizeof(st1.a)+sizeof(st1.b)+sizeof(st1.c)個,

(在vc++6.0中為4+4+4=12個)(為方便下文均以vc++6.0編譯環境為例),實際操作中也是如此。道理卻不是4+4+4=12的道理。

如:

struct number_2

st2所佔記憶體並非1+4+8=13個,而是16個》13個。這是為什麼?

我們會發現,sizeof(st2)=16,剛好是double型別的二倍,這又是為什麼?

我們將上例改為:

會發現st3記憶體占用並非1+4=5個,而是sizeof(st3)=8個,剛好是int型別的二倍,這又是為什麼??

了解過結構體內存對齊原則以後,初學時的問題才得以解決。

2、結構體在記憶體中的對齊原則:

結構體中包含有相同型別或不同型別的資料型別,如char(1位元組),int(4位元組),double(8位元組),所以結構體內存出現了乙個對齊原則:

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

即,當char a時,以char自身大小(一位元組)劃分,a占有了首位址0乙個位元組。但是當int b時,以int自身大小(四位元組)劃分,所以b從四位元組的非負整數倍開始儲存占用四個位元組,由於首位址0已被占用,所以b從第四個位址開始占用四個位元組。同理,當double c時,double也以自身大小(八字節)劃分記憶體,而前八個(0——7)已被占用,故c從第八個位址開始占用八個位元組。如下左圖:

如果去掉中間定義的int b,st2仍然佔16個位元組。因為,double c時,首位址0已被占用,c不能從0(8的0倍)開始,就只能從8(8的1倍)開始。如下右圖:

而且,double b之前空著的記憶體,在對齊下原則可以隨意增加變數,記憶體是不會增加的。如下圖:

3、記憶體的補齊原則:

當定義結構體為:

struct number_4

st4;

時發現sizeof(st4)=12,而不是4+4+1=9。

這時候就牽扯到乙個補齊原則:

在經過對齊原則分析後,檢查計算出的儲存單元是否為所有元素中所佔記憶體最大的元素的長度的整數倍,是,則結束;若不是,則補齊為它的整數倍。

即,當4+4+1=9不是結構體中記憶體最大元素b的整數倍時,要補齊成其整數倍12。如下圖左所示,如果將int換成double,sizeof(st4)=24為最大元素double的整數倍了。如下圖右所示:

總結:

結構體在記憶體中的儲存遵循著對齊與補齊的原則來儲存。

結構體內存對齊

結構體內存對齊 一 什麼是位元組對齊,為什麼要對齊?現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特 定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這...

結構體內存對齊

一 什麼是位元組對齊,為什麼要對齊?現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特 定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。對齊的...

結構體內存對齊

對齊規則 每個特定平台上的編譯器都有自己的預設 對齊係數 也叫對齊模數 程式設計師可以通過預編譯命令 pragma pack n n 1,2,4,8,16來改變這一係數,其中的n就是你要指定的 對齊係數 規則 1 資料成員對齊規則 結構 struct 的資料成員,第乙個資料成員放在offset為0的...