結構體大小與巢狀結構體大小

2021-08-17 15:24:00 字數 2110 閱讀 8968

我們在剛開始學習結構體時總覺得它的大小就是所有元素的和加起來即可,但實際上並不是這麼簡單,通常情況下要考慮位元組對齊問題,結構體各成員之間或結構體的尾部需要添補一些空白位元組。包含相同成員的結構體,如果成員宣告的順序不同,其占用的記憶體空間也可能不同。儘管在程式中可以利用sizeof獲取當前編譯條件下結構體所佔記憶體空間的大小,但深入了解結構體中成員對齊所遵循的規則也很有必要。

首先我們來說一下位元組對齊的規則,結構體成員的對齊是指成員相對於結構體首位址的偏移量應該是2^n的倍數(為什麼要說是2^n的倍數呢,因為我們內建型別元素的位元組肯定都是2^n位元組的,所以我們就說以2^n倍數對齊)。如果是以1-byte對齊時,這個成員的偏移量就很隨意了0,1,2,3,4。。。。假設2-byte對齊時,那麼成員偏移量只能是0、2、4……而4-byte對齊的時候偏移量只能是0、4、8……

我們結構體中各成員以什麼方式對齊與成員的大小有關,成員大小為a則進行a-byte對齊,即成員的偏移量應該被成員的大小整除。例如int型別的成員其偏移量必須是4的整數倍,double型別的成員其偏移量必須是8的整數倍。

#includestruct s1

x1;struct s2

x2;int main()

s1結構體a以1--byte對齊,偏移量為0即可,b是double型,偏移量只能是8,所以需要在a後加上7個位元組的空格,sizeof(x1)即為16.同理,s2中a是double型以8-byte對齊,偏移量為0即可,b是char型別,所以緊接a後,所以偏移量是8,c是short型別,按照2-byte對齊,所以偏移量是10,所以b和c之間應該補上乙個位元組空格,c之後也應補上4個位元組的空格,sizeof(x2)即為16.

如下圖:

在vc/vs的編譯器中,通過#pragma pack可以規定對齊的位元組。例如在定義結構體之前新增#pragma pack(n),則編譯器為某個成員將其對齊數設定為n,這裡n的取值可以是1、2、4、8、16,如果不是這些數,就按上文的方式處理對齊。舉個例子:

#include#pragma pack(4)

struct s

x;int main()

這個輸出結果是12,並不是我們之前計算的16,因為這時我們是以4個位元組對齊,m1後只是補全了2個位元組的空格。

我們將pack改為1或者2,答案是10,這個時候並沒有補空格,全部佔滿。

我們再將pack改為3/5.。。,答案是16,事實證明這時候並沒有採取這個對齊方式,而是預設的方式。

巢狀結構體的大小

先上**:

#include #define field_offset(s,f) (int)(&(((struct s *)(0))->f))

struct ss1

aa;

int c; //32

}ss1;

struct ss2

; int c; //16

}ss2;

int main()

先看這個,這兩個唯一的區別就是是否定義了結構體變數,從結果可以看出, 未定義結構體變數的結構體大小比較小,因為內部的結構體並不計算(內部為聯合體也是一致)。從這個結構體巢狀中我們可以看出它採用的對齊方式是採取的是結構體中的內建型別的最大元素的位元組數,而不是用內部結構體的大小當作對齊位元組,這是很重要的一點。

內部如果是聯合體,和上面基本一致,共用體定義變數的情況下採用的是共用體中位元組數最大的元素位元組,共用體中所有的變數的起始偏移都是一致的,這是與內部是結構體不同的一點。

struct ss1

aa;

int c; //24

}ss1;

printf("%d\n",field_offset(ss1,aa.cc)); //16

printf("%d\n",sizeof(ss1)); //32

結構體巢狀結構體名

結構體巢狀結構體名 前一段時間在看ddk中例子的時候,看到這樣的的結構體定義 typedef struct common device data common device data,pcommon device data typedef struct pdo device data pdo dev...

結構體中巢狀結構體

結構體的巢狀問題 結構體的自引用 self reference 就是在結構體內部,包含指向自身型別結構體的指標。結構體的相互引用 mutual reference 就是說在多個結構體中,都包含指向其他結構體的指標。1.1不使用typedef時 錯誤的方式 struct tag 1 這種宣告是錯誤的,...

結構體巢狀結構體 C語言結構體

希望今年夏天的遺憾能成為你秋天的驚喜。網易雲熱評 一 結構體概念 可以簡單理解為把不同資料型別放到一起的陣列 二 結構體宣告與初始化 1 先宣告結構體型別再定義變數 2 同時定義變數 3 直接定義結構體型別變數 include include include include struct aiyou...