jinxed - 7 months ago 28

C++ Question

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`

`0010001100010000000001100100000000000000000000000000110010000010`

as binary, however istead I'm getting

`588254914`

`00100011000100000000111011000010`

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.