问题描述
我写了下面的代码来理解按位右移操作,
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
我认为在右移操作之前a和b都等于0xFFFFFFFF
,然后在右移之后结果应该是相同的。但结果表明
a = 0xFFFFFFFF
b = 0x7FFFFFFF
好像a的MSB为1,b的MSB为0。为什么会出现这种差异?
解决方法
如果您修正错误的说明符并添加一些额外的打印输出,您会发现您的假设是错误的:
#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",b);
a = a >> 1;
b = b >> 1;
printf("a = %lx\n",a); // result: a = 0xFFFFFFFF
printf("b = %lx\n",b); // result: b = 0x7FFFFFFF
}
输出:
$ ./a.out
a = 0
b = ffffffff
a == b? No
a = ffffffffffffffff
b = ffffffff
a = 7fffffffffffffff
b = 7fffffff
记得用 -Wall -Wextra
编译以捕获这样的错误。
解决方案:更改为:unsigned long b = -1;
另一种解决方案:包括 limits.h
并使用 ULONG_MAX
。
值得注意的是,long
没有固定的宽度。如果您想要固定宽度,请使用 uint32_t
之类的类型。