对齐原则
(1) 数据成员对齐:结构struct(或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#paragma pack指定的数值和这个数据成员自身长度比较小的进行
(2) 结构(或联合)的整体对齐:#paragma pack指定的数值和结构(或联合)最大数据成员长度较小的进行
(3) 结构体内部的结构体成员要从内部最大元素大小的整数倍地址开始存储
例一:一字节对齐
第一步:成员数据对齐
#pragma pack(1)
struct AA
{
int a; //长度4 < 1 按1对齐;偏移量为0;存放位置区间[0,3]
char b; //长度1 = 1 按1对齐;偏移量为4;存放位置区间[4]
short c; //长度2 > 1 按1对齐;偏移量为5;存放位置区间[5,6]
char d; //长度1 = 1 按1对齐;偏移量为7;存放位置区间[7]
//整体存放在[0~7]位置区间,共8个字节
};
#pragma pack()
第二步:整体对齐
整体对齐系数 = min((max(int,short,char), 1) = 1,不需要再进行整体对齐
例二:二字节对齐
第一步:成员数据对齐
#pragma pack(2)
struct AA
{
int a; //长度4 < 1 按2对齐;偏移量为0;存放位置区间[0,3]
char b; //长度1 < 2 按1对齐;偏移量为4;存放位置区间[4]
short c; //长度2 = 2 按2对齐;偏移量提升到2的倍数6;存放位置区间[6,7]
char d; //长度1 < 2 按1对齐;偏移量为8;存放位置区间[8]
};
#pragma pack()
第二步:整体对齐
整体对齐系数 = min((max(int,short,char), 2) = 2,将9提升到2的倍数,10个字节
例三:四字节对齐
第一步:成员数据对齐
#pragma pack(4)
struct AA
{
int a; //长度4 = 4 按4对齐;偏移量为0;存放位置区间[0,3]
char b; //长度1 < 4 按1对齐;偏移量为4;存放位置区间[4]
short c; //长度2 < 4 按2对齐;偏移量提升到2的倍数6;存放位置区间[6,7]
char d; //长度1 < 4 按1对齐;偏移量为8;存放位置区间[8]
};
#pragma pack()
第二步:整体对齐
整体对齐系数 = min((max(int,short,char), 4) = 4,将9提升到2的倍数,12个字节
例三:八字节对齐
第一步:成员数据对齐
#pragma pack(8)
struct AA
{
int a; //长度4 < 8 按4对齐;偏移量为0;存放位置区间[0,3]
char b; //长度1 < 8 按1对齐;偏移量为4;存放位置区间[4]
short c; //长度2 < 8 按2对齐;偏移量提升到2的倍数6;存放位置区间[6,7]
char d; //长度1 < 8 按1对齐;偏移量为8;存放位置区间[8]
};//9字节
#pragma pack()
第二步:整体对齐
整体对齐系数 = min((max(int,short,char), 8) = 4,将9提升到4的倍数,12字节
例四:结构体包含结构体的运算
struct AA
{
int a; //长度4 < 8 按4对齐;偏移量为0;存放位置区间[0,3]
char b; //长度1 < 8 按1对齐;偏移量为4;存放位置区间[4]
short c;//长度2 < 8 按2对齐;偏移量提升到2的倍数6;存放位置区间[6,7]
//结构体内部最大元素为int,由于偏移量为8刚好是4的整数倍,所以从8开始存放接下来的struct FF
struct FF
{
int a1;//长度4 < 8 按4对齐;偏移量为0;存放位置区间[8,11]
char b1;//长度1 < 8 按1对齐;偏移量为12;存放位置区间[12]
short c1;//长度2 < 8 按2对齐;偏移量提升到2的倍数14;存放位置区间[14,15]
char d1;//长度1 < 8 按1对齐;偏移量为16;存放位置区间[16]
};
//整体对齐系数=min(max(int,short,char),8)=4,将偏移量提升到4的倍数20
char d;//长度1 < 8 按1对齐;偏移量为21;存放位置区间[21]
};
//整体对齐系数,min((max(int,short,char), 8)=4;偏移量提升到4的倍数24
例五:嵌套结构体
struct B
{
char e[2];//长度2 < 8 按2对齐;偏移量为0;存放位置区间[0,1]
short h; //长度2 < 8 按2对齐;偏移量为2;存放位置区间[2,3]
//结构体A内部double字节长度最长,8字节
struct A
{
int a;//长度4 < 8 按4对齐;偏移量提升8的倍数8;存放位置区间[8,11]
double b;//长度8 == 8 按8对齐;偏移量提升到8的倍数16;存放位置区间[16,23]
float c;//长度4 < 8 按4对齐;偏移量为24;存放位置区间[24,27]
}
}//28字节
//整体对齐=min(max(char e[2], short, int double, float), 8)=8
//对齐到8的整数,32字节