默认对齐规则
- 成员对齐:每个变量类型的起始地址必须是其自身大小(或编译器/平台定义的对齐值)的整数倍。
- 结构体整体对齐:结构体总大小必须是其成员中最大对齐值的整数倍。
char: 1 字节
short: 2 字节
int/float: 4 字节
double/指针(x86): 4 字节
double/指针(x64): 8 字节
struct Example1 {
char a; // 1 字节,对齐到 0
int b; // 4 字节,对齐到 4(起始地址必须是4的整数倍,所以要跳过 3 字节填充)
double c; // 8 字节,对齐到 8
};
结构体最大对齐值是8
内存布局:| a (0) | 填充3字节(1-3) | b (4-7) 必须是自身大小(4)的整数倍| c (8-15) |
总大小:16 字节(满足 double 的 8 字节对齐)
强制 4 字节对齐的方法
(1) 使用 #pragma pack (编译器指令)(不推荐,可能失效)
#pragma pack(push, 4) // 压入当前对齐设置,强制后续结构体按 4 字节对齐
struct MyStruct {
char a; // 1 字节,对齐到任意地址
int b; // 4 字节,对齐到 4 的倍数地址
double c; // 8 字节,但受 pack(4) 限制,对齐到 4 的倍数地址
};
#pragma pack(pop) // 恢复之前的对齐设置
总大小计算:
| a (0) | 填充 (1-3) | b (4-7) | c (8-15) | 总大小 = 16 字节
(2) 使用 ****alignas (C++11 标准)
struct alignas(4) MyStruct {
char a;
int b;
double c; // 若系统默认对齐为 8,此处仍会按 4 对齐
};
- 验证对齐:
static_assert(alignof(MyStruct) == 4, "Alignment error");
对齐效果验证
查看结构体大小和对齐值
struct MyStruct {
char a;//1 字节,对齐到任意地址
unsigned short b;//2 字节,对齐到 2 的倍数地址
char c[5];//1 字节,对齐到任意地址
};
int main(
int argc, char *argv[])
{
QApplication a(argc, argv);
qDebug()<<"size:"<<sizeof(MyStruct);
qDebug() << "Alignment: " << alignof(MyStruct);//多少字节对齐,由结构体成员中最大值的整数倍决定
qDebug() << "Offset of b: " << offsetof(MyStruct, b);
qDebug() << "Offset of c: " << offsetof(MyStruct, c);//地址偏移
return a.exec();
}
结果:
size: 10
Alignment: 2
Offset of b: 2
Offset of c: 4
成员布局:a(偏移:0), 填充1字节(偏移:1), b(偏移:2-3),c(偏移:4-8),填充1字节(9),总大小10字节
强制4字节对齐
#pragma pack(push, 4) //压入当前对齐设置,强制后续结构体按 4 字节对齐,这种方法在QTcreator msvc编译失效,仍然是2字节对齐
struct alignas(4) MyStruct {
char a;//1 字节,对齐到任意地址
unsigned short b;//2 字节,对齐到 2 的倍数地址
char c[5];//1 字节,对齐到任意地址
};
#pragma pack(pop) // 恢复之前的对齐设置
int main(
int argc, char *argv[])
{
QApplication a(argc, argv);
qDebug()<<"size:"<<sizeof(MyStruct);
qDebug() << "Alignment: " << alignof(MyStruct);
qDebug() << "Offset of b: " << offsetof(MyStruct, b);
qDebug() << "Offset of c: " << offsetof(MyStruct, c);
return a.exec();
}
结果:
size: 12
Alignment: 4
Offset of b: 2
Offset of c: 4
成员布局:a(偏移:0), 填充1字节(偏移:1), b(偏移:2-3),c(偏移:4-8),填充3字节(9-11),总大小12字节