关于内存对齐的一点探讨
为什么需要内存对齐
内存对齐是一种提高内存访问速度的策略,cpu在访问未对齐的内存需要经过两次内存访问,而经过内存对齐一次就可以了
计算机在读取内存的时候,是一块一块的读取的
1 | 我们认为是一个一个的读取的 |
那为什么需要内存对齐?因为如果你不理解内存对齐,有可能会导致
- 程序运行速度变慢
- 应用程序产生死锁
- 操作系统崩溃
- 你的程序会毫无征兆的出错,产生错误的结果
首先这里只关注第一个(其余3个都与平台和硬件相关),程序运行速度变慢?why?
因为如果存在以下的结构体
1 | struct Test { |
Test的内存结构是这样的
1 | |c1|i|i|i| |
那么为了读取i,cpu要读取两次并将其拼接,才能够得到i的值,为了更高的效率
可以这样摆放
1 | |c1| | | | |
这样的话就能一次性将i读取出来
1 |
|
成员对齐与整体对齐
所谓成员对齐,就如上面说的例子
1 | |c1|i|i|i| |
为了更高的读取效率,可以往后c1添加3个字节,那么为什么一定要添加3个字节?
这就和对齐系数有关了,#pragma pack(n)
可以指定对齐系数
不同平台上编译器的 pragma pack
默认值不同。而我们可以通过预编译命令#pragma pack(n), n= 1,2,4,8,16
来改变对齐系数
整体对齐与数据对齐相似但不是完全相同
如果数据对齐完成时struct
的大小不是struct
内成员自身长度最大值(sizeof
) 与 #pragma pack(n)
中的n的最小值的整数倍
注意这里是成员中长度最大的那个与n比较,而不是特定的一个成员。就要在struct
的最后添加空字节直到对齐
例如一个struct在数据对齐之后,整个的大小是6byte,但是对齐系数是4,那么就要往后添加2byte