在不同平台/编译器上,我该在哪里找到关于C++内存对齐的文档?

9

我正在寻找一份关于C++中内存对齐、典型方法、编译器之间的区别和常见陷阱的好(全面的)文档。这样可以检查我的对该主题的理解是否正确,并学习新知识。

这个问题是受到我回答另一个问题时使用以下结构的启发:

char const buf[1000] = ...;
unsigned int i = *reinterpret_cast<unsigned int*>(buf + shift); // shift can be anything

这种方法因不符合内存对齐规则而受到批评。您能否作为额外的奖励解释一下,从内存对齐的角度来看,这种方法存在什么缺陷?非常感谢您提供一个举例说明该方法不能正常工作。我知道这种方法通常是不好的,但在网络协议实现中经常使用它,所以这更多是一个实践问题,而不是理论问题。

此外,请不要在此处提到严格别名,这是另一个问题。


移位操作是否不是您系统字长的倍数?如果您试图在一个字(比如32位字)的中间获取指针,这可能会受到批评,因为这很奇怪。 - Doug T.
1
即使 shift 是 4 的倍数,也不能保证 buf 的起始地址是 4 的倍数。 - nos
“shift” 可以是任何东西,更新了问题。 - Andriy Tylychko
1
我想在这里指出,许多编译器都有非标准扩展的对齐指令,可以用于将结构体的对齐方式设置为1。将int放入一个1对齐的结构中,您确实可以安全地在任何偏移量处进行解引用。产生的开销取决于您的CPU架构;在x86上,它不应该过于痛苦。 - bdonlan
3个回答

6

非堆分配的char数组对其没有特定要求。因此,你的一千个字符的缓冲区可能在奇数偏移量上。尝试从该偏移量(显然重新解释为int指针)读取int将导致性能不佳,甚至在某些硬件上会出现总线错误,如果编译器没有将其拆分为单独的读取+位掩码操作。

堆分配的char数组保证适合存储任何对象类型,因此这始终是一个选择。

对于非堆基础存储,请使用boost::aligned_storage,它确保空间适合于一般用途。


+1:很遗憾我不能接受两个答案,所以我应该接受另一个回答了主要问题的答案。 - Andriy Tylychko

3

0
假设地址必须像PS3一样对齐为16字节。 然后想象一下移位== 1的情况。 这肯定是一个非16字节对齐的指针,在这台机器上无法工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接