如何解释位右移两个不同的结果?

How to explain the bit right shift two different results?

我得到两个不同的结果,我很困惑,代码是:

int main () 
{
    int i = 0xcffffff3;
    printf("%x\n", 0xcffffff3>>2);
    printf("%x\n", i>>2);

    return 0;
}

结果是:

33fffffc
f3fffffc

0xcffffff3 >> 2中,两个值都被视为unsigned,而在i >> 2中,isigned

因此,算术移位在带符号的情况下前置 1 位,因为数字在移位前是负数。

如果您想要与常量相同的结果,请使用 (unsigned)i >> 2 或定义 unsigned i = 0xcffffff3;

这一切都归结为 0xcffffff3。那是一个十六进制整数常量。常量的类型取决于它的大小。参考一下C11 § 6.4.4.1 ¶ 5:

The type of an integer constant is the first of the corresponding list in which its value can be represented.

Octal or Hexadecimal Constant - int, unsigned int, long int, unsigned long int, long long int, unsigned long long int

假设您的系统使用 32 位整数表示。 0xcffffff3 的类型是 unsigned int.

现在,当您执行 int i = 0xcffffff3; 时,无符号常量将转换为有符号整数。此转换产生负值。

最后,当右移时,它具有C11 §6.5.7 ¶5定义的语义:

The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2 . If E1 has a signed type and a negative value, the resulting value is implementation-defined.

移动无符号常量产生 0xcffffff3/4 并且移动 i 产生一个实现定义的值(在本例中为负整数)。