簡體   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