[英]C++ Unable to convert std::vector<BYTE> to a string or char array
[英]C++ Unable to convert vector<char> to int
我正在使用 boost ASIO 通过 TCP 流发送消息。 我首先以严格的 4 个字节长度发送正文大小。 比在服务器端,我制作了一个vector<char>
,我将其调整为 4 个字节,并将消息正文大小放在那里。 这是我如何转换 char std::vector<char> size;
输入:
_packet.body_size = static_cast<int>(_packet.size[0]);
当_packet.size[0]
保存的值不大于 124 时,此方案有效。
在这种情况下有效。 如您所见, body_size
设置为124
。
但是,如果该值大于124
例如128
,我将无法以与124
相同的方式正确解析它。
看一看:
查看设置的body_size
。 为什么我不能转换大于 124 的数字?
错误在哪里,我该如何解决?
要从向量中的 4 个单字节char
值构造(4 字节/32 位)整数,并安全地这样做,您需要将每个字符“掩码”到该整数的相关 8 位中.
您可以在短循环中使用按位或 ( |
) 和位移 ( <<
) 操作的组合来执行此操作:
#include <iostream>
#include <vector>
int main()
{
std::vector<char> cVec = { -128, 0, 0, 0 };
int32_t iVal = 0;
for (size_t i = 0; i < 4; ++i) {
iVal |= static_cast<int>(cVec[i]) << (i * 8);
}
std::cout << iVal << std::endl;
return 0;
}
以上适用于对整数使用Little-Endian 字节序列的系统(最常见的处理器,如 Intel x86/x64 系列,使用此系统)。 在 Big-Endian 系统上,您需要以相反的顺序添加字节,使用以下内容作为for
循环的“主体”:
iVal |= static_cast<int>(cVec[3-i]) << (i * 8);
注意:将向量数据的地址转换为指向 int 的指针然后取消引用它可能很诱人(正如我在评论中所建议的那样)。 然而,这是不安全的并且引入了未定义的行为,因为它违反了 C++ 语言的严格别名规则。
直接回答问题:
您只提取了第一个字节,然后将其转换为整数。 如果后续字节具有有意义的信息,则它们将“丢失”。
您打算将所有四个字节重新解释为整数。
那看起来像这样:
_packet.body_size = *reinterpret_cast<int*>(&_packet.size[0]);
但是,其他答案是正确的,因为这并不安全。 您不能采用一系列char
并假装那里存在一个int
对象。 与流行的看法相反,它不是“全部只是字节”。 🙂(尽管公平地说,它通常会在您的系统上运行。)
安全的方法是std::memcpy
:
assert(packet.size.size() >= sizeof(_packet.body_size));
std::memcpy(&_packet.body_size, &packet.size[0], sizeof(_packet.body_size));
… 或std::copy
:
assert(packet.size.size() >= sizeof(_packet.body_size));
std::copy(
packet.size.begin(),
packet.size.end(),
static_cast<char*>(&_packet.body.size)
);
这是有效的,因为相反的转换(假装int
是一个char
序列)是有效且安全的。
但是,您最好只在单个字节中进行位掩码以获得字节序安全(并确保int
大小不匹配不会杀死您!),正如 Adrian 已经展示的那样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.