1

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
abatishchev
  • 98,240
  • 88
  • 296
  • 433
Jay D
  • 3,263
  • 4
  • 32
  • 48
  • 2
    What language is this? In C/C++, just cast the value to an unsigned integer type and it will be a logical shift. – Mysticial Oct 06 '11 at 05:32
  • @Mysticial: that's the answer, essentially. – Alexey Frunze Oct 06 '11 at 05:37
  • What language and compiler? Is there need for portability of the code? What are you running this on (uCs etc)? – NightWolf Oct 06 '11 at 05:44
  • Yes , portability is important but bunch of #ifdefs should be fine(i guess) . The compilers are VS and gcc 4.X.X – Jay D Oct 06 '11 at 06:08
  • 1
    If `uniqID` is unsigned (as u64 indicates) you don't have to worry about because [the right shift would be a logical shift](http://stackoverflow.com/questions/7622/shift-operator-in-c/7632#7632). Also have a look at: [Verifying that C / C++ signed right shift is arithmetic for a particular compiler?](http://stackoverflow.com/q/1597704/237483) – Christian Ammer Oct 06 '11 at 07:25

2 Answers2

1

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.

NightWolf
  • 7,694
  • 9
  • 74
  • 121
  • Yes. So the question was is there a way to do this checking in the code with some #def or something ? – Jay D Oct 06 '11 at 06:03
  • Ah that depends on your compiler! If you can tell me what compiler you are using then we can check (a) what the logic used is and (b) if there are any #defs... I have not used them before as I just check the compiler doco to see how it does things. AS i said its a safe assumption that aslong as the type is unsigned its logical... But you need to know what compiler and version to be 100% certain. – NightWolf Oct 06 '11 at 06:07
  • A quick google search: http://gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/Integers-implementation.html#Integers-implementation and http://www.gnu.org/s/hello/manual/autoconf/Function-Portability.html – NightWolf Oct 06 '11 at 06:09
1

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 
Mysticial
  • 464,885
  • 45
  • 335
  • 332
  • Should use C++ style casting here instead of C-style (e.g. `static_cast(uniqID)`) – ross Apr 02 '16 at 00:35
  • @ross Personally, I find nothing wrong with C-style casts for numeric types. – Mysticial Apr 02 '16 at 00:38
  • Yes, C-style casts are okay for numeric types. However, if the type ever changed, these C-style casts could fall into a `reinterpret_cast`, which can fail. Not really a question of useability, but rather ease of maintainability. I still say that if you're working in C++, you should be using C++ casts. – ross Apr 04 '16 at 21:15