从 char* 缓冲区读取int32_t的惯用 cpp14 方法是什么?
What is the idiomatic cpp14 way to read an int32_t from a char* buffer?
给定一个包含 int(小端序)的字符缓冲区 c。如何将其视为int32_t?
我写了这段代码,但它感觉不像惯用的 cpp。
int32_t v;
char* p = (char*)&v;
for (int i=0; i < 4; i++) {
*(p+i) = *(c+i);
}
将二进制数据从char*
缓冲区复制到任何其他数据类型的唯一可移植方法是使用 memcpy
(或等效的字节复制 merhod,如 std::copy
或您自己的模仿此行为的 merhod)。
memcpy(&my_number, my_buffer, sizeof(my_number));
当然,缓冲区应包含给定数据类型的正确位。如果它源自同一台计算机上的相同数据tyoe的内存复制,那么字节序就不会发挥作用。否则,您必须按所需顺序(就地或在临时缓冲区中)重新排列字节,或者在整数本身中以与平台相关的方式交换字节(可能与 htonl 和 friends)。
没有神奇的惯用方法来处理字节序 — 字节序是一个 I/O 问题。要么使用 htonl()
和 ntohl()
函数(在每个系统上都可用),要么只是自己解码它们(就像您正在做的那样)。我建议编写函数来做到这一点(让你的生活更轻松,可验证)。
以便携和安全的方式解决问题,请使用memcpy
,因为 n.m. 的答案解释。否则,这里有一个更危险的技术:
请注意,这是 UB。仅当您完全确定缓冲区包含正确数量的数据并且缓冲区和数据正确对齐时,才使用以下技术。
如果确定系统的字节序与存储在char*
缓冲区中的数据之一匹配,则可以使用 reinterpret_cast
:
std::int32_t v = *reinterpret_cast<std::int32_t*>(p);
没有符合标准的方法可以执行上述转换。有关更多详细信息,请参阅此问题。
没有标准函数来发现系统的字节序。但是,给定这样一个仅在小端系统上返回 true 的函数bool is_little_endian()
,您可能会执行以下操作:
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*
才能合法地为所有其他类型的别名。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 使用std::函数映射对象方法
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- C++从另一个类访问公共静态向量的正确方法是什么
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 没有为自己的结构调用列表推回方法
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 在类定义之后定义一个私有方法
- 枚举环境变量的惯用C++14/C++17方法
- 从 char* 缓冲区读取int32_t的惯用 cpp14 方法是什么?