memcpy with initialized variable and negative numbers with cast

Viewed 204

I have

    QByteArray bytes    // Fullfilled earlier   
    char id_c = bytes[7];   
    int _id;
    _id = 0; // If I comment this result would be different
    memcpy(&_id, &id_c, 1); 
    int result = _id;

I have _id variable and if I comment "_id=0" result variable result would be different with negative number. Why? Why initializing _id with 0 would be different?! How can I do this alternatively with same result as using "_id=0" but without memcpy and unwanted castings?

This is not my code. I am interested how to get same result correctly without stupid castings.

3 Answers

Correct.

Because this statement:

memcpy(&_id, &id_c, 1); 

Is only copying a single byte from &id_c into an address representing a 4-byte integer, &_id. Only the first byte of memory occupied by _id gets anything copied into it. Without the zero init of _id first, the remaining three bytes of that value are left undefined (presumably random garbage values off the stack).

What's wrong with an "unwanted casting"? This is just as fine and the compiler generates the most efficient code.

QByteArray bytes    // Fullfilled earlier   
int _id = (int)(bytes[7]);
int result = _id;

If you want sign extended result of the unsigned byte copied into _id, then this:

int _id = (signed char)(bytes[7]);

_id = 0 is called assigning 0 value to the variable _id, if you comment that then we cannot be sure what is stored in that _id , and you are updating only one byte out of that, as it is of type int it is more than one byte in size.

You might try these net/host byte order conversions:

on linux

on windows

the only difference is the header file to use; You can use preprocessor tricks to determine the platform and choose the proper header if cross-platform programming is intended. A better approach is to use the C++20 feature std::endian. But you need to handle the conversion yourself:

#include <bit>
#include <climits>
int int_cvt(int x){
    if constexpr (endian::native==endian::big)
       return x;
    y=0;
    while(x){
        unsigned char c=x;
        x>>=std::CHAR_BIT;
        y<<=std::CHAR_BIT;
        y+=c;
    };
    return y;
};

cheers, FM.

Related