简体   繁体   中英

C++, pack integer bytes into a char array?

I'm transferring data over network, so trying to set up a header, where first 3 bytes are a message type, and the next 4 bytes are the size of the message. When I'm adding an integer, for anything over 127 bytes, I'm overflowing. How do I set up such header?

Here's a simple example. If num is 127 or less, then the output is correct, but if it's 128 or more, then the output is all messed up.

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

If num is 127 or less, then the output is correct, but if it's 128 or more, then the output is all messed up.

It appears you're talking about the following part of the code where you try to read your integer back out of the char array and then display it:

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

The problem is that x + 3 is of type char* , and when you dereference that it becomes a char value. On your system, that value is signed and integers are obviously stored in little-endian form. So, you think it "works" for values less than 128. But actually that's not even true. It will also break for values less than -128.

You see, even though you're assigning this to a int , it's still only a char . That char value is simply being copied into a larger integer type.

It looks like you actually wanted this:

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

This is called type punning (treating some memory as if it contained another type) and should be avoided !!!

Instead, you should just copy the bytes out the same way you copied them in:

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

Also beware that if you plan to transfer binary data over a network, that any machine reading this data must be aware of its endianness .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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