我想知道将std::bytes
的紧凑子数组转换为数值的安全方法是什么。我猜这段代码是:
std::array<std::byte, 12> ar = { /* some bytes */ };
uint32_t value = *reinterpret_cast<uint32_t*>(&ar[4]);
例如,很容易出错,因为它取决于编译器如何对齐数组中的值。提前感谢!
一种可靠的方法是使用std::memcpy
在uint32_t
对象上复制目标字节。每个版本的c++都需要memcpy
来安全地完成这个任务。这种模式很常见,编译器通常可以优化出副本。
#include <array>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <stdexcept>
template<class T, std::size_t N>
T read_int_from_bytes(const std::array<std::byte, N> & data, std::size_t index)
{
if(index + sizeof(T) > N) {
throw std::invalid_argument("read_int index out of bounds");
}
// Integer to copy the bytes to
T result;
// Copy the bytes
std::memcpy(&result, &(data[index]), sizeof(result));
return result;
}
下面是一个例子。这个测试创建一个值为{ 0x00, 0x10, ..., 0xB0 }
的字节数组,并从第4个字节开始读取uint32_t
。
#include <iostream>
#include <iomanip>
int main()
{
std::array<std::byte, 12> data{};
for(std::size_t i = 0; i < data.size(); ++i)
{
data[i] = static_cast<std::byte>(0x10 * i);
}
std::cout << "Ox" << std::hex << read_int_from_bytes<std::uint32_t>(data, 4);
}
当我在这里尝试时,测试产生Ox70605040
。您还可以从汇编中注意到,整个函数调用都被优化了,结果是预先计算的,这清楚地表明编译器能够通过memcpy
进行推理并完全删除它。
注意结果是未指定的,它取决于目标平台的Endianness。也就是说,第一个字节是最高的还是最低的。对于许多应用程序来说,这并不重要,但是c++ 20引入了std::endian
,您可以使用它来检查系统的Endianness。