Arithmetic vs logical shift operation in C++
I have some code that stuffs in parameters of various length (u8, u16, u32) into a u64 with the left shift operator.
Then at various places in the code i need to get back the original parameters from this big bloated parameter.
Just wondering how , in the code, should we ensure that its a logical right shift and not arithmetic one while getting back the original parameters.
So the qestion is are there any #defs or other ways to ensure and check whether the compiler will screw up?
Here's the C++ code:
u32 x , y ,z;
u64 uniqID = 0;
u64 uniqID = (s64) x << 54 |
(s64) y << 52 |
(s64) z << 32 |
uniqID; // the 开发者_运维技巧original uniqID value.
And later on while getting the values back :
z= (u32) ((uniqID >> 32 ) & (0x0FFFFF)); //20 bits
y= (u32) ((uniqID >> (52 ) & 0x03)); //2 bits
x= (u32) ((uniqID >> (54) & 0x03F)); //6 bits
The general rule is a logical shift is suitable for unsigned binary numbers, while the arithmetic shift is suitable for signed 2's comp numbers. It will depend on your compiler (gcc etc), not so much the language, but you can assume that the compiler will use a logical shift for unsigned numbers... So if you have an unsigned type one would think that it will be a logical shift.
You can always write your own method to check and do the shifting if you need some portability between compilers. Or you can use in-line asm to do this and avoid any issues (but you would be fixed to a platform).
In short to be 100% correct check your compiler doco.
This looks like C/C++, so just make sure uniqID
is an unsigned integer type.
Alternatively, just cast it:
z = (u32) ( ((unsigned long long)uniqID >> (32) & (0x0FFFFF)); //20 bits
y = (u32) ( ((unsigned long long)uniqID >> (52) & 0x03)) ; //2 bits
x = (u32) ( ((unsigned long long)uniqID >> (54) & 0x03F)) ; //6 bits
精彩评论