写入未对齐的存储

Writing to unaligned storage

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

//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)) = '[=12=]'; //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 可能能够做到这一点但我不确定这是否属实以及我将如何使用它。

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

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