Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bitwise or before casting to int32

I was messing about with arrays and noticed this. EG:

int32_t array[];
int16_t value = -4000;

When I tried to write the value into the top and bottom half of the int32 array value,

array[0] = (value << 16) | value;

the compiler would cast the value into a 32 bit value first before the doing the bit shift and the bitwise OR. Thus, instead of 16 bit -4000 being written in the top and bottom halves, the top value will be -1 and the bottom will be -4000.

Is there a way to OR in the 16 bit value of -4000 so both halves are -4000? It's not really a huge problem. I am just curious to know if it can be done.

like image 906
helloworld4890 Avatar asked Feb 15 '26 13:02

helloworld4890


2 Answers

Sure thing, just undo the sign-extension:

array[0] = (value << 16) | (value & 0xFFFF);

Don't worry, the compiler should handle this reasonably.

To avoid shifting a negative number:

array[0] = ((value & 0xFFFF) << 16) | (value & 0xFFFF);

Fortunately that extra useless & (even more of a NOP than the one on the right) doesn't show up in the code.

like image 172
harold Avatar answered Feb 17 '26 03:02

harold


Left shift on signed types is defined only in some cases. From standard

6.5.7/4 [...] If E1 has a signed type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

According to this definition, it seems what you have is undefined behaviour.

like image 42
Giorgi Moniava Avatar answered Feb 17 '26 03:02

Giorgi Moniava