内存对齐
补充一下结构体的知识。
结构体回顾
以前以为结构体的内存大小就是结构体中所有变量内存大小的总和。
但有次运行了下面的代码
1 | struct A { |
输出结果
1 | sizeof(A) = 16 |
显然,如果只是将结构体中所有变量的内存大小相加,A应该是13,B应该是14啊,真是奇怪。
原因就是为了提高内存的访问效率,C中的结构体存在内存对齐
内存对齐
对齐规则
- 成员对齐:第一个成员变量从0位置开始占用内存空间,其余每个成员的起始地址必须是其对齐数的整数倍。
对齐数 = min(成员类型的大小,编译器默认对齐数)
编译器默认对齐数可由#pragma pack(n)修改 - 结构体总大小:结构体的总大小是所有成员 最大对齐数的整数倍
- 结构体作为成员时:当结构体作为其他结构体成员时,其起始地址是自身最大对齐数的整数倍。
为什么要内存对齐
为什么要内存对齐:
主要是由于 CPU 的访问内存的特性决定,CPU 访问内存时并不是以字节为单位来读取内存,而是以机器字长为单位,实际机器字长由 CPU 数据总线宽度决定的。实际 CPU 运行时,每一次控制内存读写信号发生时,CPU 可以从内存中读取数据总线宽度的数据,并将其写入到 CPU 的通用寄存器中。比如 32 位 CPU,机器字长为 4 字节,数据总线宽度为 32 位,如果该 CPU 的地址总线宽度也是为 32 位,则其可以访问的地址空间为 [0,0xffffffff]。内存对齐的主要目的是为了减少 CPU 访问内存的次数,加大 CPU 访问内存的吞吐量。假设读取 8 个字节的数据,按照每次读取 4 个字节的速度,则 8 个字节需要 CPU 耗费 2 次读取操作。CPU 始终以字长访问内存,如果不进行内存对齐,很可能增加 CPU 访问内存的次数。
实践
回顾
再来看看A和B两个结构体。
A的内存大小 = 4+1+3(补齐的)+8 = 16
B的内存大小 = 1+4+8+1+7(补齐的)= 21 所有成员最大对齐数为8,结构体大小补全为24
小练习
如果调换一下A中变量的顺序,如下:
1 | struct C { |
结构体C的内存大小又是多少呢?
答案是24!
原因:4+8+1+7(补齐的)= 20,所有成员最大对齐数为8,结构体大小补全为24
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Derek's Blog!

