内存对齐的两个基本原则是首地址偏移量需要是min(对齐单位,成员字节数)的倍数,总字节数需要是对齐单位倍数。
本文内容参考 https://zhuanlan.zhihu.com/p/30007037
版权归忆臻所有。
内存对齐的必要性
虽然内存以字节为单位进行保存,但处理器寄存器一次性读取数据可能按照双字节、4字节、8字节等进行读取。32位系统的存取粒度是4字节,64位系统的存取力度是8字节。考虑32位系统下从地址1开始存放一个int,那么处理器需要读取两次数据,并且经过两次移位,一次拼接完成int的读取,这些导致数据读取速度的下降。内存对齐牺牲一定的存储空间,来换取更快的内存访问速度。
内存对齐规则
对齐模数
- 对齐模数:每个平台下的不同编译器都有自己默认的对齐模数,win 64 gcc32的默认对齐模数是8,centos64 gcc64默认对齐模数也是8。可以通过预编译命令#pragma pack(n)进行修改;
- 对齐单位:min(对齐模数,max(类中数据成员字节数))
对齐规则
- 第一个类成员首地址offset为0,之后每个成员首地址offset是min(对齐单位,该成员字节数)的整数倍,如有需要编译器会进行字节填充;
- 类总字节数是对齐单位整数倍,如有需要编译器会进行字节填充。
例子(win10 gcc32 环境,默认对齐模数是8)
1 |
|
B的内存分布 24字节
| 虚表指针4字节 | x 4字节 | y 8字节 | z 1字节 填充7字节 |
C的内存分布 32字节
| C的虚表指针4字节 | B的虚表指针4字节 | B::x 4字节 填充4字节 | B::y 8字节 | B::z 1字节 填充7字节 |