字節對齊-知識點整理

介紹三個概念:自身對齊值、指定對齊值、有效對齊值。

自身對齊值:數據類型本身的對齊值,例如char類型的自身對齊值是1,short類型是2;

指定對齊值:編譯器或程序員指定的對齊值,32位單片機的指定對齊值默認是4;

有效對齊值:自身對齊值和指定對齊值中較小的那個。

對齊有兩個規則:

1 基本類型變量起始地址要按一定規則對齊. 

        char 類型,其起始地址要1字節邊界上,即其地址能被1整除(即任意地址即可)
        short類型,其起始地址要2字節邊界上,即其地址能被2整除(0x0002,0x0004,0x0006.....,地址的末位能被2整除)
        int  類型,其起始地址要4字節邊界上,即其地址能被4整除(0x0004,0x0008,0x00012,0x0016......,地址的末位能被4整除)
        long類型,其起始地址要4字節邊界上,即其地址能被4整除(0x0002,0x0004,0x0006......,地址的末位能被4整除)
        float類型,其起始地址要4字節邊界上,即其地址能被4整除(0x0002,0x0004,0x0006......,地址的末位能被4整除)
        double類型,其起始地址要8字節邊界上,即其地址能被8整除 (0x0008,0x0016,0x0024......,地址的末位能被8整除)

2 結構體地址對齊需要兼顧下面三個方面

1 若結構體中最大佔用空間的成員爲int類型,則整個結構體的起始地址應以4字節爲邊界;2 且結構內成員的偏移量也要參照1中的int類型,滿足相應倍數進行對齊;3 且結構總尺寸也要對齊. 要爲最大尺寸的成員int類型的整數倍,,如果不是則要在結構最後補齊成整數倍例

舉例:

struct A{  

char a;

char b;

char c;

char d;

};  

0x0000

0x00001

0x0002

0x0003

a

b

c

d

結構體A佔4個字節,  (0x0000~0x003總內存大小爲4,爲char類型大小的倍數)

假如結構體A起始地址是0x0000,

成員a的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x0000是1的整數倍,故a存放起始地址是0x0000,佔一個字節;

成員b的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x0001是1的整數倍,故b存放起始地址是0x0001,佔一個字節;

成員c的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x0002是1的整數倍,故c存放起始地址是0x0002,佔一個字節;

成員d的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x0003是1的整數倍,故d存放起始地址是0x0003,佔一個字節;

此時結構體A的有效對齊值是其最大數據成員的自身對齊值,它的成員都是char類型,故結構體A的有效對齊值是1.

 

struct B{  

char a;

short b;

char c;

char d;

};  

0x0000

0x00001

0x0002

0x0003

0x0004

0x0005

a

x

b

b

c

d

結構體B佔6個字節(0x0000~0x0005總內存爲6,爲short 類型的3倍)

 

struct C{  

char a;

int  b;

char c;

char d;

};  

0x0000

0x00001

0x0002

0x0003

0x0004

0x0005

0x0006

0x0007

0x0008

0x0009

0x000A

0x000B

a

x

x

 

x

b

b

b

b

c

d

x

x

x爲補齊的數據,結構體C佔12個字節 (0~B 佔12字節) ,結構體C的成員佔據10個字節,而結構體C的有效對齊值是其成員b的自身對齊值4,10不是4的倍數,故還需補齊兩個字節,此時結構體C佔據12個字節,是4的倍數

成員a的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x0000是1的整數倍,故a存放起始地址是0x0000,佔一個字節;

成員b的自身對齊值4,指定對齊值4,所以有效對齊值是4,地址0x0004是4的整數倍,故b存放起始地址是0x0004,佔四個字節;

成員c的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x0008是1的整數倍,故c存放起始地址是0x0008,佔一個字節;

成員d的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x0009是1的整數倍,故d存放起始地址是0x0009,佔一個字節;

 

struct D{  

char a;

double  b;

char c;

char d;

};  

0x0000

0x00001

0x0002

0x0003

0x0004

0x0005

0x0006

0x0007

0x0008

0x0009

0x000A

0x000B

0x000C

0x000D

0x000E

0x000F

a

x

x

x

b

b

b

b

b

b

b

b

c

d

Y

Y

結構體D佔16個字節,8的倍數

注意:由於結構體D的起始地址由a開始存儲,且按4字節的指定對齊值對齊,所以b從0x0004開始存儲。

若沒有指定按4字節對齊,起始地址需要按照從0x0008開始且總尺寸大小爲8的倍數,D結構體的實際佔據0~0x0011,總共爲17;不爲8的倍數,補齊至24,則sizeof(D)= 8+8+2+6, =24;

0x0000

0x00001

0x0002

0x0003

0x0004

0x0005

0x0006

0x0007

0x0008

0x0009

0x000A

0x000B

0x000C

0x000D

0x000E

0x000F

a

x

x

x

x

 x

 

 

x

 

 

 

x

 b

 

b

b

b

b

b

 b

b

0x0010

0x00011

0x0012

0x0013

0x0014

0x0015

0x0016

0x0017

0x0018(十進制24)

0x0009

0x000A

0x000B

0x000C

0x000D

0x000E

0x000F

c

 d

 

 

 

x

x

x

x

x

x

x

           

 

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