jinxed jinxed - 4 months ago 11
C++ Question

C++ packing different data types into one long variable

G'day gents, i've got into a trap trying to pack a couple of variables into a one variable 8 byte long.

Basically, I've got a couple of short items which have small binary size and I need to pack them together to send into class which must be able to depack it back.

So I made the following:

typedef unsigned long long PACKAGE; // 8 byte (shows as _int64 in debug)
(sizeof returns '8')
unsigned int dat1 = 25; // 1 byte long max
unsigned int dat2 = 1; // 4 bit long max
unsigned int dat3 = 100; // 2 byte long max
unsigned int dat4 = 200; // 4 byte long max
unsigned int dat5 = 2; // 4 bit long max


Then I make a variable of PACKAGE type which is empty (0)

PACKAGE pack = 0;


And I want to throw variables into that pack using binary operations, I do:

pack = (dat1 << 56) | (dat2 << 52) | (dat3 << 36) | (dat4 << 4) | dat5;


it works only half-good, I calculated that I must get decimal value of pack equals to
2526526262902525058
, or

0010001100010000000001100100000000000000000000000000110010000010


as binary, however istead I'm getting
588254914
, or
00100011000100000000111011000010‬
as binary
which is somehow correct at it's tail and head but the middle part is missing off somewhere.

And when this is done I'm still about to extract the data back somehow.

Would be thankful for any advise!

Answer

Assuming that sizeof(unsigned int) != sizeof(unsigned long long), the left operand of each shift is the wrong type. Each shift operation is being truncated (probably to 32 bits).

Try, for example:

typedef unsigned long long PACKAGE; // 8 byte (shows as _int64 in debug)
(sizeof returns '8')
unsigned long long dat1   = 25;  // 1 byte long max
unsigned long long dat2   = 1;   // 4 bit long max
unsigned long long dat3   = 100; // 2 byte long max
unsigned long long dat4   = 200; // 4 byte long max
unsigned long long dat5   = 2;   // 4 bit long max

pack = (dat1 << 56) | (dat2 << 52) | (dat3 << 36) | (dat4 << 4) | dat5;

or:

typedef unsigned long long PACKAGE; // 8 byte (shows as _int64 in debug)
(sizeof returns '8')
unsigned int dat1   = 25;  // 1 byte long max
unsigned int dat2   = 1;   // 4 bit long max
unsigned int dat3   = 100; // 2 byte long max
unsigned int dat4   = 200; // 4 byte long max
unsigned int dat5   = 2;   // 4 bit long max

pack = ((PACKAGE)dat1 << 56) | ((PACKAGE)dat2 << 52) | ((PACKAGE)dat3 << 36) | ((PACKAGE)dat4 << 4) | (PACKAGE)dat5;

Note: Okay, in actuality each shift operation in which the right-hand operand is greater than the size of the left-hand type, in bits invokes undefined behavior. The typical undefined behavior is truncation, but any other behavior, up to and including global thermonuclear war, is allowed by the standard.

Comments