简体   繁体   English

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

[英]C++ Unable to convert vector<char> to int

I am using boost ASIO to send message over TCP stream.我正在使用 boost ASIO 通过 TCP 流发送消息。 I send the body size first in strictly 4 bytes length.我首先以严格的 4 个字节长度发送正文大小。 Than on server side I make a vector<char> which I resize to 4 bytes and I put the message body size there.比在服务器端,我制作了一个vector<char> ,我将其调整为 4 个字节,并将消息正文大小放在那里。 Here is how I convert vector of char std::vector<char> size;这是我如何转换 char std::vector<char> size; to int:输入:

_packet.body_size = static_cast<int>(_packet.size[0]);

This scenario works when the value which is kept inside _packet.size[0] is not bigger of 124._packet.size[0]保存的值不大于 124 时,此方案有效。

在此处输入图片说明

And in this scenario works.在这种情况下有效。 body_size is set to 124 as you can see.如您所见, body_size设置为124

However if the value gets bigger than 124 like 128 for example I am not able to parse it correctly in the same way as I did with 124 .但是,如果该值大于124例如128 ,我将无法以与124相同的方式正确解析它。

Take a look:看一看:

在此处输入图片说明

See to what number is set body_size .查看设置的body_size Why am I not able to convert bigger than 124 numbers?为什么我不能转换大于 124 的数字?

Where is mistake and how can I fix it?错误在哪里,我该如何解决?

To construct a (4-byte/32-bit) integer from the 4 single-byte char values in your vector, and to do so safely , you will need to 'mask-in' each character into the relevant 8 bits of that integer.要从向量中的 4 个单字节char值构造(4 字节/32 位)整数,并安全地这样做,您需要将每个字符“掩码”到该整数的相关 8 位中.

You can do this using a combination of bitwise or ( | ) and bit-shift ( << ) operations in a short loop:您可以在短循环中使用按位或 ( | ) 和位移 ( << ) 操作的组合来执行此操作:

#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;
}

The above will work for systems that use Little-Endian byte sequences for integers (most common processors, like the Intel x86/x64 family, use this system).以上适用于对整数使用Little-Endian 字节序列的系统(最常见的处理器,如 Intel x86/x64 系列,使用此系统)。 On Big-Endian systems, you will need to add the bytes in reverse order, using the following as the 'body' of the for loop:在 Big-Endian 系统上,您需要以相反的顺序添加字节,使用以下内容作为for循环的“主体”:

        iVal |= static_cast<int>(cVec[3-i]) << (i * 8);

Note: It may be tempting to just cast the address of the vector's data to a pointer-to-int and then dereference that (as I suggested in the comments).注意:将向量数据的地址转换为指向 int 的指针然后取消引用它可能很诱人(正如我在评论中所建议的那样)。 However, this is unsafe and introduces undefined behaviour , as it violates the Strict Aliasing Rules of the C++ language.然而,这是不安全的并且引入了未定义的行为,因为它违反了 C++ 语言的严格别名规则

To directly answer the question:直接回答问题:

You've extracted just the first byte, then converted it to an integer.您只提取了第一个字节,然后将其转换为整数。 If the subsequent bytes have meaningful information, they are "lost".如果后续字节具有有意义的信息,则它们将“丢失”。

What you intended was to reinterpret all four bytes as an integer.您打算所有四个字节重新解释为整数。

That would look like this:那看起来像这样:

_packet.body_size = *reinterpret_cast<int*>(&_packet.size[0]);

However, the other answers are correct in that this is not safe .但是,其他答案是正确的,因为这并不安全 You cannot take a sequence of char s and pretend that an int object exists there.您不能采用一系列char并假装那里存在一个int对象。 Contrary to popular belief, it's not "all just bytes".与流行的看法相反,它不是“全部只是字节”。 🙂 (Though it will often appear to work on your system, to be fair.) 🙂(尽管公平地说,它通常会在您的系统上运行。)

The safe approach is std::memcpy :安全的方法是std::memcpy

assert(packet.size.size() >= sizeof(_packet.body_size));
std::memcpy(&_packet.body_size, &packet.size[0], sizeof(_packet.body_size));

… or std::copy : … 或std::copy

assert(packet.size.size() >= sizeof(_packet.body_size));
std::copy(
   packet.size.begin(),
   packet.size.end(),
   static_cast<char*>(&_packet.body.size)
);

This works because the opposite conversion (pretending an int is a sequence of char s) is valid and safe.这是有效的,因为相反的转换(假装int是一个char序列)有效且安全的。

You'd be better off, though, just bitmasking in the individual bytes to get endian-safety (and to ensure int size mismatches don't kill you!), as Adrian has already shown.但是,您最好只在单个字节中进行位掩码以获得字节序安全(并确保int大小不匹配不会杀死您!),正如 Adrian 已经展示的那样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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