Reputation: 259
I have a hex number 0x8F
(10001111 in binary). I want to right shift that value, so the new one would be 0xC7
(11000111). I tried with:
unsigned char x = 0x8F;
x=x>>1;
but instead of 0xC7 I got 0x47? Any ideas on how to do this?
Upvotes: 6
Views: 1550
Reputation: 129314
That's because what you want is a "rotate right", not "shift right". So you need to adjust for the lowest bit "falling off":
x = ((x & 1) << CHAR_BITS-1) | (x >> 1);
should do the trick.
[And at least some compilers will detect this particular set of operations and convert to the corresponding ror
or rol
instruction]
Upvotes: 8
Reputation: 2617
Right shifting or left shifting will fill with 0
s respectively on the left or on the right of the byte. After shifting, you need to OR
with the proper value in order to get what you expect.
x = (x >> 1); /* this is now 01000111 */
x = x | ( 0x80 ); /* now we get what we want */
Here I'm OR
ing with the byte 10000000
which is 0x80
resulting in 0xC7
.
Making it more concise, it becomes:
x = (x >> 1) | (unsigned char)0x80;
Upvotes: 2
Reputation: 114461
Right shift on an unsigned quantity will make new zeros to enter, not ones.
Note that right shift is not a right rotation. To do that you need
x = (x >> 1) | (x << 7)
Upvotes: 14