結構體的記憶體分配

2021-06-19 03:56:32 字數 2320 閱讀 9457

假設這台機器 sizeof(char) = 1   sizeof(int) = 4    sizeof(double) = 8

列舉型別只為最寬的資料分配記憶體,在不同是時候,用的是同一塊記憶體;

在預設情況下,vc規定各成員變數存放的起始位址相對於結構的起始位址的偏移量必須為該變數的型別所占用的

位元組數的倍數。下面列出常用型別的對齊方式(vc6.0,32位系統)。

型別 對齊方式(變數存放的起始位址相對於結構的起始位址的偏移量)

char 偏移量必須為sizeof(char)即1的倍數

short 偏移量必須為sizeof(short)即2的倍數

int 偏移量必須為sizeof(int)即4的倍數

float 偏移量必須為sizeof(float)即4的倍數

double  偏移量必須為sizeof(double)即8的倍數

各成員變數在存放的時候根據在結構中出現的順序依次申請空間,同時按照上面的對齊方式調整位置,

空缺的位元組vc會自動填充。同時vc為了確保結構的大小為結構的位元組邊界數(即該結構中占用最大空間的型別

所占用的位元組數)的倍數,所以在為最後乙個成員變數申請空間後,還會根據需要自動填充空缺的位元組。

結構體的記憶體分配依賴於結構成員的型別;

一:    struct s ;

首先來看對結構體 struct s ;       的記憶體分配

第1個成員偏移量為0,是4(int型大小)的整數倍。所以為其分配四個位元組的空間,

第2個成員 c 為char型,他的大小為1,首先假設在成員i和c之間沒有填充位元組,由於i是整型,佔4個位元組那麼在沒有填充之前,第2個成員c 相對於結構體的偏移量為 4,是1 ( char型的大小)的4倍,符合此條件,所以系統在給結構體第2個成員分配記憶體時,不會在i和c之間填充位元組以到達對齊的目的。 所以在緊接著i 後為c 分配乙個位元組,現在結構體的大小應該是5 (4+1); 但是結構體要求:結構體的總大小為結構體最寬基本型別成員大小的整數倍,如有需要編譯器會在最末乙個成員之後加上填充位元組(trailing padding)。所以編譯器會在後面填充3個位元組, 因此該結構體的實際大小: sizeof(struct s) = 8;

再看結構體 struct s ; 

上面說到: 如果該結構體只包括i、c兩個成員時,編譯器會自動在最末乙個成員之後加上3 填充位元組,但是現在有了第3 個成員d, 該怎麼分配呢? 根據上面的規則,由於成員c 相對於結構體的偏移量為 4,他1 ( char型的大小)的4倍, 所以在緊接著i 後為c 分配乙個位元組,現在結構體的大小應該是5 (4+1),那麼成員d 的偏移量就應該是5,但是5 並不是8 (double 型的大小)的倍數,會在成員c 之後(或者說d 之前)填充3個位元組,以使d 的偏移量到達8而成為4的整數倍。然後為d 分配8 個位元組,因此現在struct s 的大小就是16 (4 + 1 + 3 + 8);

同理,由於指標佔4 個位元組    所以

struct s ;   的大小為20

由於沒有為陣列a 指定大小,不為其分配空間, 因此struct s ;的大小為20;

二: struct s1;       的大小為28 = 1+3+20+1+3

位元組對齊的細節和編譯器實現相關,但一般而言,滿足三個準則:

1) 結構體變數的首位址能夠被其最寬基本型別成員的大小所整除;

2) 結構體每個成員相對於結構體首位址的偏移量(offset)都是成員大小的整數倍,如有需要編譯器會在成員之間加上填充位元組(internal adding);

3) 結構體的總大小為結構體最寬基本型別成員大小的整數倍,如有需要編譯器會在最末乙個成員之後加上填充位元組(trailing padding)。

對於上面的準則,有幾點需要說明:

1) 前面不是說結構體成員的位址是其大小的整數倍,怎麼又說到偏移量了呢?因為有了第1點存在,所以我們就可以只考慮成員的偏移量,這樣思考起來簡單。想想為什麼。結構體某個成員相對於結構體首位址的偏移量可以通過巨集offsetof()來獲得,這個巨集也在stddef.h中定義,如下:

#define offsetof(s,m) (size_t)&(((s *)0)->m)

例如,想要獲得s2中c的偏移量,方法為size_t pos = offsetof(s2, c);// pos等於4

2) 基本型別是指前面提到的像char、short、int、float、double這樣的內建資料型別,這裡所說的「資料寬度」就是指其sizeof的大小。由於結構體的成員可以是復合型別,比如另外乙個結構體,所以在尋找最寬基本型別成員時,應當包括復合型別成員的子成員,而不是把復合成員看成是乙個整體。但在確定復合型別成員的偏移位置時則是將復合型別作為整體看待。

更詳細的解釋: 裡面主要是對sizeof的用法進行了總結,還說到了pack,

結構體的記憶體分配

記憶體大小和系統有關,如32位系統和64位系統,同一資料型別,記憶體分配大小不一 假設這台機器是sizeof char 1 sizeof int 4 sizeof double 8 列舉型別只為最寬的資料分配記憶體,在不同的時候,用的是同一塊記憶體 在預設情況下,規定各成員變數的起始位址相對於結構的...

結構體的記憶體分配

假設這台機器 sizeof char 1 sizeof int 4 sizeof double 8 列舉型別只為最寬的資料分配記憶體,在不同是時候,用的是同一塊記憶體 在預設情況下,vc規定各成員變數存放的起始位址相對於結構的起始位址的偏移量必須為該變數的型別所占用的 位元組數的倍數。下面列出常用型...

共用體結構體的記憶體分配

共用體表示幾個變數共用乙個記憶體位置,在不同的時間儲存不同的資料型別和不同長度的變數。在union中,所有的共用體成員共用乙個空間,並且同一時間只能儲存其中乙個 成員變數 的值。下例表示宣告乙個共用體foo union foo 再用已宣告的共用體可定義共用體變數。例如用上面說明的共用體定義乙個名為b...