我最近开始考虑对齐..。这是我们通常不需要考虑的事情,但我已经意识到一些处理器要求对象沿4字节边界对齐。这到底是什么意思,以及哪些特定系统有对齐要求?
假设我有一个任意的指针:
unsigned char* ptr
现在,我尝试从内存位置检索一个双精度值:
double d = **((double*)ptr);
这会造成问题吗?
发布于 2009-08-06 02:05:27
这肯定会在某些系统上造成问题。
例如,在基于ARM的系统上,您无法寻址未与4字节边界对齐的32位字。这样做将导致访问冲突异常。在x86上,您可以访问这种未对齐的数据,尽管性能会受到一些影响,因为必须从内存中获取两个单词,而不是一个单词。
发布于 2009-08-06 02:33:26
以下是对对齐的描述:
4.1.1对齐单词、双字、四字和双四字
单词、双字和四字不需要在自然边界上的内存中对齐。字、双字和四字的自然边界分别是偶数地址、可被4整除的地址和可被8整除的地址。然而,为了提高程序的性能,数据结构(尤其是堆栈)应该尽可能在自然边界上对齐。这是因为处理器需要两次存储器访问才能进行非对齐的存储器访问;对齐的访问只需要一次存储器访问。跨越4字节边界的字或双字操作数或跨越8字节边界的四字操作数被视为未对齐,并且需要两个单独的内存总线周期进行访问。
一些在双四字上操作的指令要求内存操作数在自然边界上对齐。如果指定了未对齐的操作数,则这些指令会生成通用保护异常(#GP)。双四字的自然边界是可被16整除的任何地址。在双四字上操作的其他指令允许不对齐访问(不会生成一般保护异常)。然而,从存储器访问未对齐的数据需要额外的存储器总线周期。
请不要忘记,参考手册是负责任的开发人员和工程师的最终信息来源,因此,如果您处理的是英特尔CPU等有详细记录的内容,请查看参考手册中有关该问题的说明。
发布于 2009-08-06 03:51:02
是的,这可能会导致许多问题。C++标准实际上并不能保证它能正常工作。你不能随意地在指针类型之间进行转换。
当您将字符指针转换为双指针时,它将使用reinterpret_cast
,这将应用实现定义的映射。您不能保证结果指针将包含相同的位模式,或者它将指向相同的地址或任何其他地址。在更实际的术语中,也不能保证您正在读取的值是正确对齐的。如果数据是以一系列字符的形式写入的,那么它们将使用字符的对齐要求。
至于对齐意味着什么,本质上就是值的起始地址应该可以被对齐大小整除。例如,地址16在1、2、4、8和16字节边界上对齐,因此在典型的CPU上,这些大小的值可以存储在那里。
地址6没有在4字节边界上对齐,所以我们不应该在那里存储4字节的值。
值得注意的是,即使在不强制或要求对齐的CPU上,访问未对齐值通常仍会显著减慢。
https://stackoverflow.com/questions/1237963
复制相似问题