首页 > 解决方案 > C++,将整数字节打包成一个字符数组?

问题描述

我正在通过网络传输数据,因此尝试设置一个标头,其中前 3 个字节是消息类型,接下来的 4 个字节是消息的大小。当我添加一个整数时,对于超过 127 个字节的任何内容,我都会溢出。如何设置这样的标题?

这是一个简单的例子。如果 num 为 127 或更少,则输出正确,但如果为 128 或更多,则输出全部混乱。

#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>

using namespace std;

string bytesAsStr(char* src, int size)
{
    stringstream ss;
    ss << std::hex;
    for (int i = 0; i < size; i++)
    {
        ss << std::setw(2) << std::setfill('0') << (int)src[i] << " ";
    }

    return ss.str();
}

int main()
{
    // 3 chars + 1 int 
    const int size = 3 + sizeof(int);
    char x[size];
    memcpy(x, "lsa", 3);

    int num = 129;
    memcpy(x + 3, &num, sizeof(int));

    cout << bytesAsStr(x, size) << endl;

    int out = *(x + 3);
    cout << "out: " << out << endl;
}

标签: c++

解决方案


如果 num 为 127 或更少,则输出正确,但如果为 128 或更多,则输出全部混乱。

看来您正在谈论代码的以下部分,您尝试从 char 数组中读取整数然后显示它:

int out = *(x + 3);
cout << "out: " << out << endl;

问题在于它x + 3是 type char*,当你取消引用它时它变成了一个char值。在您的系统上,该值是有符号的,并且整数显然是以小端形式存储的。所以,你认为它对小于 128 的值“有效”。但实际上这甚至不是真的。对于小于 -128 的值,它也会中断。

你看,即使你将它分配给 a int,它仍然只是 a char。该 char 值只是被复制到更大的整数类型中。

看起来你实际上想要这个:

int out = *(int*)(x + 3);  // DON'T DO THIS!

这称为类型双关语(将某些内存视为包含另一种类型)并且应该避免

相反,您应该像复制它们一样复制字节:

int out;
memcpy(&out, x + 3, sizeof(out));

另请注意,如果您计划通过网络传输二进制数据,则任何读取此数据的机器都必须知道其字节顺序


推荐阅读