为什么要对齐 ?
我们在上文引用的规范中有这么一段话:
This is done in order to speed up memory accesses of instances of the structure type.
翻译成中文就是 “这(指对齐操作)是为了加快结构体类型数据的内存访问速度”。
访问一个对齐的结构体中的数据会比访问一个非对齐的结构体要快!
这是因为现代大多数处理器在访问内存时,都会以一定的大小为单位,如 32 位的处理器会以 4 字节进行内存访问,64 位的处理器会以 8 字节进行内存访问。这也印证了引文中提到的:
it would not be atypical to see structures padded to align on four- or eight-byte boundaries.(在四字节或八字节边界上对齐的结构并不罕见)
如果一个数据正好存放于这样的一个字节边界上,处理器就能够一次性、高效地读取或写入数据。一旦数据没有对齐,例如对于 32 位的处理器来说,如果跨越两个 4 字节边界存放一个整数(大小 4 字节),那么处理器就需要进行两次内存访问来读取或写入这个整数,导致性能的下降。
这时候可能有朋友会有这样的疑问:
对于一个四字节的变量,我在地址 0、1、2、3 存放处理器能够一次读取出来,那我放到地址 1、2、3、4 不是依然只占用了 4 个字节的空间吗,处理器只需要将读取的偏移地址修改为 1 ,不是照样能一次性读取出来吗?
这个理论看似很合理,确实,仅以我们人类的思维来说是没有任何问题的。但机器不一样。
实际上大部分处理器由于其电路复杂度与成本性价比等原因,在设计之初就决定了只能从与其总线宽度对齐的地址取数据,一旦一个数据跨边界存储,则处理器需要执行两次内存访问操作才能够操作完整的数据。就如上文存放在 1、2、3、4 地址的四字节变量,处理器需要先读取 0-3 区域的 1、 2、3,再读取 4-7 区域的 4 ,最后将其拼接,才能得到 1、2、3、4 这个完整的数据。
并且,有部分处理器完全不支持非对齐的内存访问,一旦代码中访问了非对齐的内存,就会导致硬件异常或者崩溃,无法恢复!
由此可见,内存对齐对于系统的稳定、高效运行是非常关键的,尤其是在一些工业设备上,如果由于非对齐的内存访问并且造成了系统崩溃,其后果是无法估量的!
|