繁体   English   中英

C++ 无法转换向量<char>到 int

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM