![](/img/trans.png)
[英]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.