结构体对齐学习稿

先来说说为什么要有边界对齐:

 

简单说,任何CPU都有一个固定的基本长度,下面以32CPU为例(也有64位或其他的)。CPU在工作时只能按照该长度的整倍数为边界进行内存操作。即只能从地址0326496...处进行存取,而不能从275883等非边界地址处进行。如果一定要取这些非边界地址处的内容,则必须用若干个操作将其凑出来,因而大大影响存取效率。

 

另一方面,一个结构体的设计长度却并不一定是32的倍数,例如一个包含六个字符的结构其设计长度仅为48位。如果多个这样的结构在内存中顺着摆放,则许多结构的起始地址将不在边界处。因此,编译程序总是会将每个结构的尾部都加入一些必要的空白,将其凑成32的整数倍。这就是边界对齐的基本道理。

 

在没有#pragmapack宏的情况下,存在三条原则:

 

原则1、普通数据成员对齐规则:第一个数据成员放在offset0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始

比如int32位机为4字节,则要从4的整数倍地址开始存储

 

原则2、结构体成员对齐规则:如果一个结构里有某些结构体成员,则该结构体成员要从其内部最大元素大小的整数倍地址开始存储。

struct a里存有struct bb里有charintdouble等元素,那b应该从8的整数倍开始存储

 

原则3、结构体大小对齐规则:结构体大小也就是sizeof的结果,必须是其内部成员中最大的对齐参数的整数倍,不足的要补齐

 

还有一条原则:成员对齐有一个重要的条件,即每个成员按自己的方式对齐。其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里默认是8字节)中较小的一个对齐。并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节

 

如果有#pragmapack宏,对齐方式按照宏的定义来。比如上面的结构体前加#pragma pack(1),内存的布局就会完全改变。有了#pragma pack(1),内存不会再遵循原则1和原则3了,按1字节对齐。

 

#pragma pack规定的对齐长度,实际使用的规则是:

结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。

也就是说,当#pragmapack的值等于或超过所有数据成员长度的时候,这个值的大小将不产生任何效果。

而结构整体的对齐,则按照结构体中最大的数据成员和 #pragma pack指定值之间,较小的那个进行。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值