結構體數據對齊原則的一些補充

數據對齊基本原則請看上一篇博客,這裏針對結構體嵌套以及結構體含有static變量的情況做一些補充:

舉個例子:

一、對於node3,含有靜態數據成員 

typedef struct node3
{
    int a;
    short b;
    static int c;
}S3;

則sizeof(S3)=8.這裏結構體中包含靜態數據成員,而靜態數據成員的存放位置與結構體實例的存儲地址無關(注意只有在C++中結構體中才能含有靜態數據成員,而C中結構體中是不允許含有靜態數據成員的)。其在內存中存儲方式如下:

  |--------int--------|   4字節

  |--short-|----|----|    4字節

  而變量c是單獨存放在靜態數據區的,因此用siezof計算其大小時沒有將c所佔的空間計算進來。

二、再看結構體嵌套的情況:

typedef struct node1
{
    int a;
    char b;
    short c;
}S1;
typedef struct node5
{
    bool a;
    S1 s1;
    double b;
    int c;
}S5;
sizeof(S5)=32。

對於變量a,其自身對齊參數爲1,#pragma pack(n)爲8,則a的最終對齊參數爲1,爲它分配1字節的空間,它相對於結構體起始地址的偏移量爲0,能被1整除;

  對於s1,它的自身對齊參數爲4(對於結構體變量,它的自身對齊參數爲它裏面各個變量最終對齊參數的最大值),#pragma pack(n)爲8,所以s1的最終對齊參數爲4,接下來的地址相對於結構體起始地址的偏移量爲1,不能被4整除,所以需要在a後面填充3字節達到4,爲其分配8字節的空間;(這裏不能把s1看作整體,其大小爲8,所以認爲對齊參數爲8,結構體嵌套的情況要把結構體“打散”來看對齊參數)

  對於變量b,它的自身對齊參數爲8,#pragma pack(n)的默認值爲8,則b的最終對齊參數爲8,接下來的地址相對於結構體起始地址的偏移量爲12,不能被8整除,所以需要在s1後面填充4字節達到16,再爲b分配8字節的空間;

  對於變量c,它的自身對齊參數爲4,#pragma pack(n)的默認值爲8,則c的最終對齊參數爲4,接下來相對於結構體其實地址的偏移量爲24,能夠被4整除,所以直接爲c分配4字節的空間。

  此時結構體所佔字節數爲1+3+8+4+8+4=28字節。

  對於整個結構體來說,各個變量的最終對齊參數爲1,4,8,4,最大值爲8,#pragma pack(n)默認值爲8,所以最終結構體的大小必須是8的倍數,因此需要在最後面填充4字節達到32字節。其存儲如下:

   |--------bool--------|    4字節

   |---------s1---------|    8字節

   |--------------------|     4字節

   |--------double------|    8字節

   |----int----|---------|     8字節 

  另外可以顯示地在程序中使用#pragma pack(n)來設置系統默認的對齊參數,在顯示設置之後,則以設置的值作爲標準,其它的和上面所講的類似,就不再贅述了,讀者可以自行上機試驗一下。如果需要取消設置,可以用#pragma pack()來取消。


再看一個例子:

struct A

{

short a1;

short a2;

short a3;

}A1;

struct B

{

char* a1;

char buf[5];

}B1;

struct C

{

B a;

A a2;

}C1;

sizeof(C)=20

前面說的結構體嵌套要打散,並不是說把C變成這樣

struct C

{

char* a1;

char buf[5];

short a1;

short a2;

short a3;

}C1;

然後sizeof(C)=16=4+5+1(填充)+2+2+2

打散是爲了找最大對齊字節數。

首先a的起始地址爲0a作爲結構體,爲其分配的大小爲12,這時候把a2“打散,求最大對齊字節數爲sizeof(short)=2,12能整除2,所以a2的起始地址爲12,再給a2分配6個字節內存,這樣總共有12+6=18個字節,對於整個結構體C來說,各個變量的最終對齊參數爲41222,最大值爲4,所以最終結構體的大小必須是4的倍數,因此需要在最後面填充2字節達到20字節。

其存儲如下:

|------char*--------|    4字節

|------char[5]------|     5字節

|-------------------|     3字節

|--------short------|    2字節

|--------short------|    2字節

|--------short------|    2字節

|----------|           2字節


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章