改善C++ 程序的150个建议学习之建议10:优化结构体中元素的布局

建议10:优化结构体中元素的布局
下面的代码片段定义了结构体A和B:
struct A // 结构体A
{
int a;
char b;
short c;
};
struct B // 结构体B
{
char b;
int a;
short c;
};
在32位机器上,char、short、int三种类型的大小分别是1、2、4。那么上面两个结构体的大小如何呢?结构体A中包含了一个4字节的int,一个1字节的char和一个2字节的short,B也一样,所以A、B的大小应该都是4+2+1 = 7字节。但是,实验给出的却是另外的结果:
sizeof(strcut A) = 8, sizeof(struct B) = 12

其原因还要从字节对齐说起。现代计算机中内存空间都是按照字节来划分的,从理论上来讲,对变量的访问可以从任何地址开始;但在实际情况中,为了提升存取效率,各类型数据需要按照一定的规则在空间上排列,这使得对某些特定类型的数据只能从某些特定地址开始存取,以空间换取时间,这就是字节对齐。

结构体默认的字节对齐一般满足三个准则:
(1)结构体变量的首地址能够被其最宽基本类型成员的大小所整除。
(2)结构体每个成员相对于结构体首地址的偏移量(offset)都是成员自身大小的整数倍,如有需要,编译器会在成员之间加上填充字节(Internal Adding)。
(3)结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节(Trailing Padding)。

按照这三条规则再去分析结构体A和B,就不会对于上述的结果一脸诧异了。这两个结
构体在内存空间中的排列如图1-2所示(灰色网格表示的字节为填充字节)。

在编程应用中,如果空间紧张,需要考虑节约空间,那么就需要将结构体中的各个变量按照上面的原则进行排列。基本的原则是:把结构体中的变量按照类型大小从小到大依次声明,尽量减少中间的填充字节。也可以采用保留字节的形式显式地进行字节填充实现对齐,以提高存取效率。其实这就是时间与空间的博弈。如下面的代码片段所示,其中的reserved成员对程序没有什么意义,它只是填补空间以达到字节对齐的目的:
struct A // 结构体A
{
int a;
char b;
char reserved; // 保留字节,空间换时间
short c;
};
struct B // 结构体B
{
char b;
char reserved1[3]; // 保留字节1,空间换时间
int a;
short c;
char reserved2[2]; // 保留字节2,空间换时间
};
在某些时候,还可以通过编译器的pack指令调整结构体的对齐方式。#pragma pack的
基本用法为:
#pragma pack( n )     n为字节对齐数,其取值为1、2、4、8、16,默认是8。
#pragma pack(1)// 设置1字节对齐
struct A // 结构体A
{
int a;
char b;
short c;
};
将结构体A的对齐方式设为1字节对齐,那么A就不再有填充字节了,sizeof(A)的结

果即为各元素所占字节之和7。


请记住:了解结构体中元素的对齐规则,合理地为结构体元素进行布局。这样不仅可以有效地节约空间,还可以提高元素的存取效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值