字节对齐
规则
成员对齐:结构体第一个成员偏移量为 0,后续成员的起始地址必须是指定对齐大小的整数倍。如果不满足,插入填充字节;
整体对齐:结构体的总大小必须是结构体中最大成员大小的整数倍。如果不够,末尾补全;
顺序影响:成员的声明顺序直接影响内存占用。将占用空间大的成员放在前面通常能减少填充;
语法
alignof:查询对齐要求
#include<cstddef>// 查询对齐要求size_t align=alignof(int);// C++11// 动态对齐分配alignas(16)charbuffer[1024];auto*ptr=new(buffer)alignas(16)MyClass();// 对齐检查boolisAligned=(reinterpret_cast<uintptr_t>(ptr)%16==0);alignas:强制指定对齐
structalignas(16)AlignedStruct{charc;inti;// 整个结构体按16字节对齐};structCustomAlign{charc;alignas(8)inti;// i按8字节对齐shorts;};#pragma pack
#pragmapack(1)// 按1字节对齐(紧凑模式)structPack1{charc;// 1字节inti;// 4字节,紧跟在c后面shorts;// 2字节};#pragmapack()// 恢复默认对齐#pragmapack(2)// 按2字节对齐structPack2{charc;// 1字节inti;// 4字节,偏移量对齐到2的倍数shorts;// 2字节};#pragmapack()#pragmapack(push,1)// 保存当前对齐值并设置为1structPackPush{charc;inti;shorts;};#pragmapack(pop)// 恢复之前的对齐值attribute((aligned))(GCC/Clang)
struct__attribute__((aligned(16)))GCCAligned{charc;inti;};structGCCPacked{charc;inti;shorts;}__attribute__((packed));// 紧凑排列原因
- 可移植性:某些硬件架构不支持访问非对齐的内存地址,强行访问,CPU 会抛异常;
- 性能优化:现代 CPU 读取内存通常 4 或 8 字节进行;
- 对齐访问:一次内存总线周期即可读完数据;
- 非对齐访问:如果一个 int 跨越了两个 4 字节边界,CPU 需要进行两次读取操作并进行拼接,效率大幅降低;