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?
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
.
User contributions licensed under CC BY-SA 3.0