0

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;
}
3
  • If you take the time to figure out exactly why the output is "messed up", the problem, and the trivial solution, should be obvious. Do you understand how, exactly, is the output "messed up"? Commented Oct 20, 2020 at 1:16
  • Base types like char or int are not as clearly defined in C++ as they could be. In this case, char is implicitly signed, so can be -128 to +127. If you want 0 to 255, it needs to be an unsigned char. Better might be to use types defined in <cstdint>, such as uint8_t (unsigned 8 bit int). Commented Oct 20, 2020 at 1:34
  • *(x + 3) is of type char. Are you trying to read a int out of that? In that case, use memcpy to copy those bytes into a int value. Commented Oct 20, 2020 at 1:37

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.