在 C 语言,编译器给 struct 的内存会有字节对齐的要求。字节对齐的目的是为了提高访问速度,这和 CPU 与内存之间的通信方式有关。
以 x86 架构为例,系统的数据总线宽度为 32 bit. 实际上,内存是按字 (word) 访问的,一个字的宽度和数据总线宽度相同。内存可以抽象为一个这样的设备:
端口 | 宽度 | 方向 | 说明 |
---|---|---|---|
clk | 1 | in | 时钟信号 |
addr | 34 | in | 地址 |
write | 1 | in | 是否写入 |
en | 1 | in | 是否输出 |
data | 32 | in/out | 数据接口 |
内存根据 addr 端口输入的地址,读取或改写对应地址处的字。这里的地址,是按字为单位计算的。
但是在 x86 指令集(以及 C 语言)中,地址是按字节计算的。这实际上是 CPU 中的硬件抽象了对内存的访问,但内存的硬件限制,就是每个内存周期只能访问一个字,所以就产生了字节对齐的问题。
以一个 32 bit 的 int a
为例,当 a
在内存中的位置刚好对应一个内存字, 即 &a % 4 == 0
时,CPU 可以用一个内存周期来访问这个 int. 如果这个 int 和一个内存字不对齐,那么 CPU 就需要用两个内存周期,读取两个字,从中取出这个 int 的内容。(以上讨论忽略 cache 的存在)
为了达到最高的访问效率,编译器会在 struct 中添加 padding 来满足对齐要求。在 x86 架构上,对齐要求是 4 字节。在这种情况下,对于小于 4 字节的数据类型,按数据类型本身的宽度对齐;对于大于 4 字节的数据类型,按照 4 字节对齐。例如:
在 x86 架构下编译运行,应该输出
0x2
0x4
0xC
0x10
0x14
0x14
Posted Saturday 1 November 2014 Share
- You might also like: