将包含std::bytes的std::数组转换为数值

  • 本文关键字:std 转换 包含 bytes 数组 c++
  • 更新时间 :
  • 英文 :


我想知道将std::bytes的紧凑子数组转换为数值的安全方法是什么。我猜这段代码是:

std::array<std::byte, 12> ar = { /* some bytes */ };
uint32_t value = *reinterpret_cast<uint32_t*>(&ar[4]);

例如,很容易出错,因为它取决于编译器如何对齐数组中的值。提前感谢!

一种可靠的方法是使用std::memcpyuint32_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。

最新更新