字节对齐

为什么要写有关字节对齐的东西呢?字节对齐应该是最基础的问题了,我原以为对字节对齐比较了解了。但是最近遇到了字节对齐的麻烦事。说麻烦其实也不麻烦,总而言之是自己对字节对齐没有理解透彻。所以就查查了字节对齐的具体定义和使用,发现自己对字节对齐的了解是很肤浅的。

那么为什么要字节对齐呢?因为各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些构架的cpu在访问某种没有字节对齐的数据类型时会出错。字节对齐还关乎cpu的存取效率。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那 么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据。

在不同平台下字节对齐后的存储空间不同,比如windows和linux。windows默认的字节对齐的有效值为8个字节,而linux默认的字节对齐的有效值为4个字节,并且如果设置#pragma pack (8), linux下的字节对齐的有效值也是4,因为它不支持大于4的有效对齐值。因此在不同平台下操作的时候,得到的size是不同的(我遇到过类似的问题)。

在说明字节对齐的时候,我们先引入几个概念,这样能更方便我们理解字节对齐的概念:

1. 数据类型本身的对齐值:顾名思义,很好理解的,比如 32位系统下,int的对齐值为4, short 为 2, long 为 4, double 为8;

2. 结构体或类的自身的对齐值: 即类或结构体中的基本数据类型自身对齐值中的最大值。比如

struct test
{
char a;
double b;
int c;
}
该结构体自身的对齐值为double的对齐值,应该为8;

3. 设置的对齐值:可以通过#pragma pack (n)来设置字节的对齐值,其中n就是指定的字节对齐值。也可以利用__attribute__((aligned(n)))来指定字节对齐值(Linux下有效,其他平台不清楚);

4. 结构体或类的有效对齐值:这个是通过比较设定的对齐值和结构体或类自身的对齐值来确定的,有效对齐值就是它们中较小的一个对齐值。比如对于test结构体,如果我们设置了#pragma pack(4),那么在计算sizeof(test)的时候,我们要按照4字节的对齐值来结算,结果就是20;


定义了上面四个概念后,我们在来说说如何计算结构体或类的字节数(计算基本类型的字节大小是没有意义的):

还是计算上面的test结构体,在vc下默认的字节对齐有效值为8byte。结构体中包含一个char类型(占1字节),那么结构体的首地址(设为0)是满足char类型对齐的(0是1的整数倍);第二个数据为double(占8字节),那么地址1是不符合double数据类型的(1不是8的整数倍),也就是我们需要在double类型之前填充7个字节,此时double类型数据的地址是8(8是8的整数倍);第三个数据是int类型(占4个字节),它的地址可以是16(16是4的整数倍),满足字节对齐。也就是此时test结构体所占字节数为20。但是我们需要考虑整个结构体的字节对齐情况,这时结构体的有效对齐值登场了。由于结构体的有效对齐值是8,那么整个结构体所占的字节数必须是8的整数倍,这可以通过填充4个字节来实现。也就是test结构体所占的字节数应该是24。


如果我们将设置的对齐值设置为4,那么结构体test的有效值就应该是4(4 < 8),此时test所占的字节数可以是20了,因为20是4的整数倍。


其实字节对齐就是要保证任何类型数据所占的字节数必须是他有效对齐值的整数倍,而且该数据类型的地址也必须他有效对齐值的整数倍。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值