字节对齐-知识点整理

介绍三个概念:自身对齐值、指定对齐值、有效对齐值。

自身对齐值:数据类型本身的对齐值,例如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

      

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值