一、内存为什么要对齐
虽然所有的变量都是保存在特定地址的内存中,但最好还是按照内存对齐的要求来存储。这主要出于两个方面的原因考虑:
- 平台原因:
不是所有的硬件平台(特别是嵌入式系统中使用的低端处理器)都能访问任意地址上的任意数据,某些硬件平台只能访问对齐的地址,否则会出现硬件异常。 - 性能原因:
如果数据存放在未对齐的内存空间中,则处理器访问变量时需要进行两次内存访问才能完整读取该变量的值,而对齐的内存访问仅需一次访问。
二、内存对齐的规则
对于结构(或联合)的各个成员,第一个成员位于偏移为 0,以后每个数据成员的偏移量必须是
#pragma pack指定的数值和结构体(或联合)中最大数据成员长度 这2个数值中较小的一个
的倍数。
使用伪代码表示:min(#pragma pack, 结构最大数据成员长度) * N
在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐也按照
#pragma pack指定的数值和结构(或联合)最大数据成员长度这2个数值中较小的一个
进行。
如果没有使用
#pragma pack
指令来显式的指定内存对齐的字节数,则按照默认字节数来对齐,各个平台的默认对齐规则如下:32位CPU默认按照4字节对齐;64位CPU默认按照8字节对齐。
三、#pragma pack 命令
1 |
四、结构体内存对齐示例
在 64 位系统上编译下面的测试程序,已知在 64 位系统上各类型占用字节数如下:
1 | char 1字节 |
示例代码如下:
1 |
|
按照第二节所讲的内存对齐规则,分析如下:
因为结构体中最大的数据成员长度为 int(即 4 字节),而且#pragma pack(8)
指令指定按照 8 字节对齐,所以min(4,8) = 4
,故我们可以知道结构体 A 按照 4 字节对齐。
下图是结构体 A 按照 4 字节对齐的内存布局(需要注意的是“内存不是填充在 s5 后面,而是填充在 c 后面”):
从图我们很容易知道sizeof(A) = 12
.
文章图片带有“CSDN”水印的说明:
由于该文章和图片最初发表在我的CSDN 博客中,因此图片被 CSDN 自动添加了水印。