给定一个包含int(小端)的char缓冲区c。 如何将其读作int32_t?
我写了这段代码,但它没有感觉到惯用的cpp。
int32_t v;
char* p = (char*)&v;
for (int i=0; i < 4; i++) {
*(p+i) = *(c+i);
}
答案 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*
可以合法别名所有其他类型。