从char *缓冲区读取int32_t的惯用cpp14方法是什么?

时间:2017-10-07 12:00:22

标签: c++ c++14 endianness

给定一个包含int(小端)的char缓冲区c。 如何将其读作int32_t?

我写了这段代码,但它没有感觉到惯用的cpp。

int32_t v;
char* p = (char*)&v;
for (int i=0; i < 4; i++) {
    *(p+i) = *(c+i);
}

4 个答案:

答案 0 :(得分:7)

二进制数据从char*缓冲区复制到任何其他数据类型的唯一可移植方式是使用memcpy(或等效的字节复制方法,例如{{} 1}}或你自己的一个模仿这种行为。)

std::copy

当然缓冲区应该包含给定数据类型的正确位。如果它来自同一台机器上的来自相同数据的内存,那么字节顺序就不起作用了。否则,您必须按所需顺序重新排列字节(在适当位置或在临时缓冲区中),或者以平台相关的方式在整数本身中交换字节(可能使用htonl和朋友)。

答案 1 :(得分:6)

没有神奇的惯用方法来处理字节序 - 字节序是一个I / O问题。使用htonl()ntohl()函数(可在每个系统上使用)或只是自己解码(正如您所做)。我建议编写功能(让你的生活更轻松,更可验证)。

答案 2 :(得分:5)

如果您想以便携和安全的方式解决问题,请使用memcpy作为n.m.'s answer explains。否则,这是一种更危险的技术:

请注意,这是UB。如果您完全确保缓冲区包含适量的数据并且缓冲区和数据是<,则仅使用以下技术strong>正确对齐

如果您确定系统的字节顺序与char*缓冲区中存储的数据相匹配,则可以使用reinterpret_cast

std::int32_t v = *reinterpret_cast<std::int32_t*>(p);

没有符合标准的方式进行上述转换。有关详细信息,请参阅this question

答案 3 :(得分:3)

没有标准功能来发现系统的字节顺序。但是,假设这样的函数bool is_little_endian()仅在小端系统上返回true,则可能会执行以下操作:

std::uint32_t read_from_little_endian(char* buf)
{
    std::uint32_t u;

    if(is_little_endian())
        std::copy(buf, buf + sizeof(u), (char*)&u);
    else
        std::reverse_copy(buf, buf + sizeof(u), (char*)&u);

    return u;
}

重要的一点是始终将std::uint32_t*投放到char*,因为只有char*可以合法别名所有其他类型。