C/C++的内存对齐
内存对齐内存对齐是 编译器自动安排结构体成员在内存中的存放位置并且在成员之间、结构体末尾自动插入填充字节padding让每个成员的起始地址满足特定倍数要求规则第⼀个成员在与结构体偏移量为0的地址处。其他成员变量要对⻬到对⻬数对⻬数 编译器默认的⼀个对⻬数与该成员⼤⼩的较⼩值的整数倍的地址处。如果结构体里面嵌套另一个结构体内部结构体的对齐单位 内部结构体最大基础成员的大小。结构体最后的总大小必须是整个结构体最大基础成员大小的整数倍。成员排完不够倍数在结构体末尾补 padding。在 vs 中默认对齐数是 8。例子以下例子在 vs 2022 编译器下执行structA{inta;charb;charc;};structB{charb;inta;charc;};printf(%zu\n,sizeof(A));// 结果为 8printf(%zu\n,sizeof(B));// 结果为 12结构体 A 和 B 拥有完全相同的成员变量但是计算出来的内存大小却不同。分析A 和 B 的成员变量类型为 int4字节char 1字节4 1 ,故最大成员的大小为4字节;vs 默认对齐数为 8 字节8 4 ,故结构体的对齐数为4字节;结构体 A中成员 a 为 int 占用地址偏移量从 0 到 3成员 b 为 char占用地址偏移量 为 4同理成员 c 为 5为了符合对齐数 4字节的整数倍结构体末尾补上 2字节则整个结构体的偏移量为 0 到 7 共 8 字节;// 示意图01234567a a a a b c \ \结构体 B中成员 b 为 char 占用地址偏移量为 0 成员 a 为 int为了对⻬到对⻬数⼤⼩的整数倍的地址处b 后面补上 3字节则 a 占用地址偏移量 为 4 到 7同理得成员 c 为 8为了符合对齐数 4字节的整数倍结构体末尾补上 3字节则整个结构体的偏移量为 0 到 11 共 12 字节;// 示意图01234567891011b \ \ \ a a a a c \ \ \为什么要有内存对齐内存对齐的出现是为了适配CPU的访问规则提升内存读写效率。CPU访问内存不是单字节读取的而是按照固定块2/4/8 字节叫访问粒度读取。比如CPU一次性读取 4字节时如果我们没有内存对齐规则地去访问结构体structA{charb;inta;charc;};// 假设没有内存对齐的示意图01234567b a a a a c这里成员 a 跨了两个内存块CPU 就需要读两次内存再拼接、裁剪速度变慢。内存对齐好处和坏处好处CPU 读写更快兼容更多硬件。坏处填充字节 padding结构体占用内存变大。内存对齐是空间换时间的典型例子。