【问题标题】:Writing to unaligned storage写入未对齐的存储
【发布时间】:2021-02-06 14:00:13
【问题描述】:

我有一些值要写入原始字节数组,在精确定义的位置,以通过网络发送它们。

//These are computed somewhere else in the program (and converted to little-endian regardless of platform):
using float32_t = float; static_assert(sizeof(float32_t) == 4);
uint32_t someInteger = 42;
float32_t someFloat = 4.2f;
bool someBoolean = true;
uint16_t someIndex = 42, someCRC1 = 42;

我的第一个解决方案有效并产生了正确的结果,但内存清理程序警告我有关未对齐的写入:

char* data = someBuffer.data(); //points directly into allocated raw bytes
(*reinterpret_cast<uint32_t *>(data     )) = someInteger;
(*reinterpret_cast<bool     *>(data +  4)) = someBoolean;
(*reinterpret_cast<float32_t*>(data +  5)) = someFloat; //unaligned
(*reinterpret_cast<uint16_t *>(data +  9)) = someIndex; //unaligned
(*reinterpret_cast<uint16_t *>(data + 11)) = someCRC;   //unaligned

所以我想出了第二种解决方案,方法是重新排序一些值并插入一个 1 字节的缓冲区以在两者之间对齐。

char* data = someBuffer.data(); //points directly into allocated raw bytes
(*reinterpret_cast<uint32_t *>(data     )) = someInteger;
(*reinterpret_cast<float32_t*>(data +  4)) = someFloat;
(*reinterpret_cast<bool     *>(data +  8)) = someBoolean;
(*reinterpret_cast<char     *>(data +  9)) = '\0'; //buffer for memory alignment
(*reinterpret_cast<uint16_t *>(data + 10)) = someIndex;
(*reinterpret_cast<uint16_t *>(data + 12)) = someCRC; //this has to be the last value!

但是我更希望有第一个排序并且没有对齐字节。 这可能独立于平台还是我必须依赖支持未对齐的商店指令?我听说使用std::memcpy 可能能够做到这一点,但我不确定如果这是真的,我将如何使用它。

【问题讨论】:

  • @EricPostpischil 这也适用于例如ARM 商店必须在哪里对齐?
  • 由 C++ 标准的规则定义。这意味着任何符合 C++ 的实现都必须正确实现它。 memcpy 被定义为按字节复制数据,前提是源和目标不重叠。所以对齐是无关紧要的。它将字节从一个地方复制到另一个地方。如果编译器可以确定源对齐和目标对齐是令人满意的,它可以分别使用对齐加载和对齐存储指令。如果不能,它将酌情使用加载字节、存储字节和/或其他指令。

标签: c++ c++17 memory-alignment


【解决方案1】:

使用std::memcpy,如std::memcpy(data + 5, &amp;someFloat, sizeof someFloat);。它是由 C++ 标准的规则定义的,与问题中显示的方式使用 reinterpret_cast 不同,一个好的编译器会在适当的情况下将其优化为简单的加载和存储指令。

请注意,被复制对象的大小取决于 C++ 实现;您有责任确保它们与发送的缓冲区中布局的大小相匹配。此外,对象的表示很大程度上依赖于实现,尤其是它们的字节存储在内存中的顺序,因此您还有责任确保表示与通过网络发送的消息中的预期相匹配。在某些 C++ 实现中,您可能需要反转对象中的字节。并且您必须确保发送和接收系统对float 使用相同的格式,以此类推。

【讨论】:

  • In some C++ implementations, you may need to reverse the bytes within objects 或反向字节对 - 理论上。我想在实践中没有很多(或任何?)中间端 C++ 实现。
  • 很好,这行得通。我知道大小(因此是 uint32_t 而不是无符号)和字节序(我预先转换)。我假设的一件事是该实现使用 IEEE-754 进行浮点数(我不知道是否存在任何其他实现)。
猜你喜欢
  • 2017-04-16
  • 1970-01-01
  • 1970-01-01
  • 2021-04-30
  • 1970-01-01
  • 2019-12-06
  • 2010-11-07
  • 2018-01-24
  • 1970-01-01
相关资源
最近更新 更多