Why are the results different when I did bitwise right shift in C language?

-2

I wrote the following code to understand the bit-wise right shift operation,

unsigned long a = 0;
unsigned long b = 0xFFFFFFFF;
a = ~a;                   // now a is equal to b
a = a >> 1; 
b = b >> 1; 
printf("a = %x\n", a);    // result: a = 0xFFFFFFFF
printf("b = %x\n", b);    // result: b = 0x7FFFFFFF

I though that before the right shift operation a and b were both equal to 0xFFFFFFFF, and then after the right shift the results ought to be identical. But the results showed that

  • a = 0xFFFFFFFF
  • b = 0x7FFFFFFF

It seemed the MSB of a got 1, while the MSB of b got 0. Why did this difference happen?

c
bit-shift
asked on Stack Overflow Jan 28, 2021 by ZhaoxiLooksLikeAFakeName • edited Jan 30, 2021 by dbush

1 Answer

3

If you fix the wrong specifier and add some extra printouts, you'll see that your assumption is wrong:

#include <stdio.h>

int main(void) {
    unsigned long a = 0;
    unsigned long b = 0xFFFFFFFF;
    printf("a = %lx\n", a);   
    printf("b = %lx\n", b);    
    a = ~a;                   // now a is equal to b

    printf("a == b? %s\n", a == b ? "Yes" : "No");

    printf("a = %lx\n", a);   
    printf("b = %lx\n", b);   
    a = a >> 1; 
    b = b >> 1; 
    printf("a = %lx\n", a);    // result: a = 0xFFFFFFFF
    printf("b = %lx\n", b);    // result: b = 0x7FFFFFFF
}

Output:

$ ./a.out 
a = 0
b = ffffffff
a == b? No
a = ffffffffffffffff
b = ffffffff
a = 7fffffffffffffff
b = 7fffffff

Remember to compile with -Wall -Wextra to catch bugs like this.

Solution: Change to: unsigned long b = -1; Another solution: Include limits.h and use ULONG_MAX.

It's worth noting that long does not have a fixed width. If you want fixed width, then use types like uint32_t.

answered on Stack Overflow Jan 28, 2021 by klutt • edited Jan 28, 2021 by klutt

User contributions licensed under CC BY-SA 3.0