Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why can't you shift a uint16_t [duplicate]

I am trying to fill a 64-bit unsigned variable by combining 16-bit and 8-bit values:

uint8_t byte0 = 0x00;
uint8_t byte1 = 0xAA;
uint8_t byte2 = 0x00;
uint8_t byte3 = 0xAA;

uint16_t hword0 = 0xAA00;
uint16_t hword1 = 0xAAAA;

uint64_t result = ( hword0 << 32 ) + ( byte3 << 24 ) + 
                  ( byte2 << 16 ) + ( byte1 << 8 ) + ( byte0 << 0  );

This gives me a warning.

 left shift count >= width of type [-Wshift-count-overflow]
 uint64_t result = ( hword0 << 32 )
like image 739
Sajesh S F Avatar asked Dec 03 '22 18:12

Sajesh S F


2 Answers

hword0 is 16 bits long and you request for a 32 bit shift. Shifting more than the number of bits - 1 is undefined.

Solution is to convert your components to the destination type : uint64_t result = ( ((uint64_t)hword0) << 32 ) + etc.

like image 170
Jean-Baptiste Yunès Avatar answered Dec 06 '22 08:12

Jean-Baptiste Yunès


As opposed to your question tile, you can shift a uint16_t. But you cannot shift it (losslessly) by more than its width.

Your input operand's type is applied to the output operand as well, so in your original question, you have a uint16_t << 32 which is 0 (because any value shifted by 32 to the left and then clipped to 16 bits is 0), and so are nearly all of your uint8_t values.

The solution is simple: before shifting, cast your values to the appropriate type suitable for shifting:

uint64_t result = ( (uint64_t)hword0 << 32 ) + 
( (uint32_t)byte3 << 24 ) + ( (uint32_t)byte2 << 16 ) + ( (uint32_t)byte1 << 8  ) + ( (uint32_t)byte0 << 0  );
like image 31
glglgl Avatar answered Dec 06 '22 06:12

glglgl