为什么我在C语言中按位右移结果不一样?

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

为了理解位右移操作,我写了下面的代码,

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的最高位是1,而b的最高位是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", 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
}

输出:

$ ./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.

这样的类型