一 自然对齐
各个类型自然对齐,即其起始内存地址必须是其类型本身的整数倍。
对于结构体来说,结构体的起始内存地址,必须是结构体中成员最大长度类型的整数倍。
结构体自然对齐应遵守如下规则
1 数据成员对齐规则
在默认情况下,结构体中各成员变量存放的起始地址相对于结构体的起始地址的偏移量:
应该是sizeof(成员变量类型)或者sizeof(成员变量类型)的倍数。
如果结构体中某个成员变量不是基本类型,比如是子结构体,它的起始地址相对于父结构体起始地址的偏移量:
应该是子结构体中最大的基本类型的整数倍。
2 整体对齐规则
结构体占用内存的总大小也有约束条件,为最大的基本类型内存长度的整数倍。
代码如下:
typedef struct a
{
char c1;
long i;
char c2;
}A
按照自然对齐的规则1:c1与结构体起始地址偏移为0,i偏移为3(必须是i类型long的的倍数),c2偏移为8
按照自然对齐的规则2:现在偏移0-偏移8的9个字节被占用,结构体大小必须是最大成员变量类型long的倍数,所以sizeof(a)为12
typedef struct b
{
char c1;
char c2;
long i;
}B
按照自然对齐的规则1:c1与结构体起始地址偏移为0,c2偏移为1,i偏移为4(必须是i类型long的的倍数),
按照自然对齐的规则2:现在偏移0-偏移7的8个字节被占用,结构体大小必须是最大成员变量类型long的倍数,所以sizeof(a)为8
二 强制对齐
#pragma pack(push) //保存当前对齐状态
#pragma pack(n) //定义对齐单元大小为n
定义结构体
#pragma pack(pop) //恢复保存的对齐状态
强制对齐的规则
1 数据成员对齐规则:
n字节对齐是指结构体中成员变量的内存地址与结构体起始地址的偏移量为:
min(sizeof(基本类型), n)的整数倍
2 整体对齐规则:
结构体的总大小也有约束条件:
min(sizeof(基本类型), n)的整数倍
可见,如果设置#pragma pack(1),就等于禁掉了数据对齐。
栈上对齐方式:
在X86平台,栈上对齐方式是整数相关类型按照4字节对齐,浮点数按照8字节对齐;在X64平台,栈上是按照16字节对齐。