优化结构体中元素的布局
在下面的代码片段定义了结构体A和B:
struct A
{
int a;
char b;
short c;
}
struct B
{
char b;
int a;
short c;
}
在32 位机器上,char、short、int 三种类型大小分别是1、2、4。那么上面两个结构体的大小如何呢?
sizeof(struct A)=8
sizeof(struct B)=12
其原因还要从字节对齐说起:
现代计算机中内存空间都是按照字节来划分的,从理论上来讲,对变量的访问可以从任何地址开始;但是实际情况中,为了提升存取效率,各类型数据需要按照一定的规则在空间上排序,这使得对某些特定类型的数据只能从某些特定地址开始存取,以空间换取时间,这就是字节对齐。
结构体默认字节对齐一般满足三个准则:
(1)结构体变量的首地址能够被其最宽基本类型成员的大小所整除。
(2)结构体每个成员相对于结构体首地址的偏移量都是成员自身大小的整数倍,如有需要,编译器会在成员之间加上填充字节。
(3)结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节。
按照这三条规则再去分析结构体A和B,就不会对上述结果一脸满然
其中灰色网格表示填充。
在编程应用中,如果空间紧张,如果考虑节约空间,那么久需要将结构体的各个变量按照上面的原则进行排列。基本的原则是:把结构体重的变量按照类型大小从小到大依次声明,尽量减少中间的填充字节。
在某些时候,还可以通过编译器的pack指令调整结构体的对齐方式。#pragma pack的基本用法为:
pragma pack(n)
n为字节对齐数,其取值为1、2、4、8、16,默认是8
#pragma pack(1)//设置1字节对齐
struct A
{
int a;
char b;
short c;
}
将结构体对齐方式设置为1字节对齐,那就是不再有填充字节了,sizeof(A)的结果即为各元素所占字节之和7.