Bitshift (rotation) with hexadecimal in C

1.6k views Asked by At

I'm trying to rotate hexadecimal numbers in C. The problem I have is that, with each loop. more zeros occur in the number.

Here is my code:

int main (void) {
  int hex = 0x1234ABCD;
  for(int i=0; i<12;i++,hex <<=4){
    printf("0x%04x %d ",hex,hex );
    pattern(hex);
  }
    return 0;
}

I saw some other code on this site which added & 0x0F to the shift, but it is not working for me.

Here are my results with the compiler

0x1234abcd 305441741  0001 0010 0011 0100 1010 1011 1100 1101
0x234abcd0 592100560  0010 0011 0100 1010 1011 1100 1101 0000
0x34abcd00 883674368  0011 0100 1010 1011 1100 1101 0000 0000
0x4abcd000 1253888000  0100 1010 1011 1100 1101 0000 0000 0000
0xabcd0000 -1412628480  1010 1011 1100 1101 0000 0000 0000 0000

Thank you for your help.

2

There are 2 answers

2
Gerhardh On BEST ANSWER

There is no operator that does a rotation for you. You need to combine 2 shift operations. Also you should use unsigned values when doing bitshift operations.

int main (void) {
  unsigned int hex = 0x1234ABCD;
  for(int i=0; i<12;i++) {
    printf("0x%04x %d ",hex,hex );
    pattern(hex);
    unsigned int upper = hex >> (sizeof(hex)*CHAR_BIT - 4);
    hex <<= 4;
    hex |= upper & 0x0F;
  }
  return 0;
}
0
Adrian Mole On

When you use the left-shift (<<) operator on a number, shifting by n bits, then the most significant n bits of that number are lost, and the least significant n bits are filled with zeros (as you have noticed).

So, in order to perform a bitwise rotation, you need to first 'save' those top 4 bits, then put them back (using the | operator after shifting them down to the bottom).

So, assuming a 32-bit int size, something like this:

#include <stdio.h>

int main(void)
{
    int hex = 0x1234ABCD;
    for (int i = 0; i < 12; i++) {
        printf("0x%04x %d ", hex, hex);
        pattern(hex);
        int save = (hex >> 28) & 0x0F; // Save TOP four bits of "hex" in BOTTOM 4 of "save"
        hex <<= 4;    // Now shift the bits to the left ...
        hex |= save;  // ... then put those saved bits in!
    }
    return 0;
}

Note: We mask the save value with 0x0F after the shift to make sure that all other bits are 0; if we don't do this then, with negative numbers, we are likely to get those other bits filled with 1s.