一、对齐说明1.结构体对齐的原因是来自硬件要求以及访问性能2.对齐的规则分为基本对齐自然对齐编译器指令对齐3.结构体对齐内存不加4.struct alignment是c编译器为了优化内存访问性能来次啊用的一种内存布局策略5.结构体中的变量成员相对于结构体的起始地址base_address的offset便宜了必须是这个成员对齐要求的整数倍也就是offse_addresssizeof(current_member_type)*N;这个条件必须满足。6.结构体总大小结构体的总大小必须是其最大成员对齐要求的整数倍即结构体末尾可能需要填充字节以便数组对齐7.嵌套结构体嵌套结构体的对齐要求等于其内部最大成员的对齐要求。二、案例#include stdio.hstruct A {char c; // 1 字节int i; // 4 字节short s; // 2 字节};struct B {int i; // 4 字节short s; // 2 字节char c; // 1 字节};int main() {printf(sizeof(A) %zu\n, sizeof(struct A)); // 输出 12可能printf(sizeof(B) %zu\n, sizeof(struct B)); // 输出 8可能return 0;}布局分析假设 4 字节对齐x86 环境struct Ac 放在偏移 0对齐要求 1满足。下一个成员 i 要求 4 字节对齐当前偏移 1 不是 4 的倍数因此编译器在 c 后填充 3 字节i 放在偏移 4。s 要求 2 字节对齐当前偏移 8 是 2 的倍数直接放置占用 2 字节偏移 8~9。结构体最大对齐要求是 4来自 int当前总大小为 10 字节需要填充到 4 的倍数末尾填充 2 字节最终大小为 12。struct Bi 放在偏移 0。s 要求 2 字节对齐偏移 4 满足放置占用偏移 4~5。c 要求 1 字节对齐偏移 6 满足放置占用偏移 6。最大对齐要求 4当前大小为 7 字节末尾填充 1 字节最终大小为 8。这个例子说明将较大对齐的成员放在前面可以减小结构体大小。三、结构体嵌套对齐struct Inner {int a;char b;};struct Outer {char c;struct Inner in;int d;};Inner 的对齐要求 max(4,1) 4大小 4 1 填充到 4 的倍数 8。Outer 布局c 偏移 0。in 需要 4 字节对齐填充 3 字节in 从偏移 4 开始占用 8 字节偏移 4~11。d 需要 4 字节对齐偏移 12 满足放置偏移 12~15。最大对齐 4总大小 16 已经对齐最终 16。四、指令对齐一#pragma pack(1) // 按 1 字节对齐取消所有填充struct Packed {char c;int i;short s;};#pragma pack() // 恢复默认// sizeof(Packed) 会变成 142 7 字节五、指令对齐二struct __attribute__((packed)) Packed {char c;int i;short s;};// 大小也为 7 字节六、指令对齐三struct alignas(16) Aligned16 {int i;char c;};// 结构体整体按 16 字节对齐大小会被调整为 16 的倍数
结构体对齐
一、对齐说明1.结构体对齐的原因是来自硬件要求以及访问性能2.对齐的规则分为基本对齐自然对齐编译器指令对齐3.结构体对齐内存不加4.struct alignment是c编译器为了优化内存访问性能来次啊用的一种内存布局策略5.结构体中的变量成员相对于结构体的起始地址base_address的offset便宜了必须是这个成员对齐要求的整数倍也就是offse_addresssizeof(current_member_type)*N;这个条件必须满足。6.结构体总大小结构体的总大小必须是其最大成员对齐要求的整数倍即结构体末尾可能需要填充字节以便数组对齐7.嵌套结构体嵌套结构体的对齐要求等于其内部最大成员的对齐要求。二、案例#include stdio.hstruct A {char c; // 1 字节int i; // 4 字节short s; // 2 字节};struct B {int i; // 4 字节short s; // 2 字节char c; // 1 字节};int main() {printf(sizeof(A) %zu\n, sizeof(struct A)); // 输出 12可能printf(sizeof(B) %zu\n, sizeof(struct B)); // 输出 8可能return 0;}布局分析假设 4 字节对齐x86 环境struct Ac 放在偏移 0对齐要求 1满足。下一个成员 i 要求 4 字节对齐当前偏移 1 不是 4 的倍数因此编译器在 c 后填充 3 字节i 放在偏移 4。s 要求 2 字节对齐当前偏移 8 是 2 的倍数直接放置占用 2 字节偏移 8~9。结构体最大对齐要求是 4来自 int当前总大小为 10 字节需要填充到 4 的倍数末尾填充 2 字节最终大小为 12。struct Bi 放在偏移 0。s 要求 2 字节对齐偏移 4 满足放置占用偏移 4~5。c 要求 1 字节对齐偏移 6 满足放置占用偏移 6。最大对齐要求 4当前大小为 7 字节末尾填充 1 字节最终大小为 8。这个例子说明将较大对齐的成员放在前面可以减小结构体大小。三、结构体嵌套对齐struct Inner {int a;char b;};struct Outer {char c;struct Inner in;int d;};Inner 的对齐要求 max(4,1) 4大小 4 1 填充到 4 的倍数 8。Outer 布局c 偏移 0。in 需要 4 字节对齐填充 3 字节in 从偏移 4 开始占用 8 字节偏移 4~11。d 需要 4 字节对齐偏移 12 满足放置偏移 12~15。最大对齐 4总大小 16 已经对齐最终 16。四、指令对齐一#pragma pack(1) // 按 1 字节对齐取消所有填充struct Packed {char c;int i;short s;};#pragma pack() // 恢复默认// sizeof(Packed) 会变成 142 7 字节五、指令对齐二struct __attribute__((packed)) Packed {char c;int i;short s;};// 大小也为 7 字节六、指令对齐三struct alignas(16) Aligned16 {int i;char c;};// 结构体整体按 16 字节对齐大小会被调整为 16 的倍数