【问题标题】:>> shift operator not working as expected>> 班次操作员未按预期工作
【发布时间】:2012-08-25 17:28:11
【问题描述】:

我正在学习 C 语言。我有这个代码,如果需要可以提供更多:

int result = 0;
int mask1 = 0x0000ffff;
mask1 = mask1 >> 28;

当我使用 gdb 并打印 /x mask1 时,我得到了 0x0,这是正确的。 那为什么会这样:

int result = 0;
int mask1 = 0xffffffff;
mask1 = mask1 >> 28;

print 0xffffffff

不应该打印0x0000000f,因为我要左移 28 位吗?

这与 int 在我的 64 位机器上占用的位数有关吗? 我查看了this,但它并没有完全回答所有问题。

【问题讨论】:

  • mask1 设为unsigned int,您将体验到您所期望的行为(即逻辑右移)。
  • 阅读务实的程序员,书中有一节题为“Select is not broken”。它描述了您在此处遇到的问题。

标签: c gdb


【解决方案1】:

负整数右移的行为是实现定义的。一种常见的行为是算术移位,它进行符号扩展。这样做的好处是右移也是除以 2 的幂(四舍五入为负无穷大),就像正数一样。

【讨论】:

    【解决方案2】:

    您正在向右移动。右图:>>,左图:<<

    通常,当您将(有符号的)整数右移时,会假定您正在更改 value 而不是 sign:这就是 Daniel 所说的 签名扩展。标准并不要求这样做,并非所有平台都这样做。

    实际上,在使用二进制补码的系统上,这意味着负值的新高位将用1 填充,正值将用0 填充。

    例如,在 8 位 2s 补码系统上:

    before          after >> 1
    11111110 = -2   11111111 = -1 (so new top bit was 1)
    00000010 = +2   00000001 = +1 (so new top bit was 0)
    

    【讨论】:

    • 负整数右移的结果是实现定义的。不能保证保持负数。
    【解决方案3】:

    负整数的按位右移是实现定义的。

    gcc 的作用如下:

    对有符号整数(C90 6.3、C99 6.5)的一些按位运算的结果。

    有符号的`>>'通过符号扩展作用于负数。

    http://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html

    【讨论】:

      【解决方案4】:

      如果将 0xffffffff 打印为整数,您将意识到它被视为 -1。

      Bitshift 对负数的工作方式不同,它用 1 填充最高位。所以基本上,0xffffffff >> 1 == 0xffffffff。

      如果您将掩码声明为unsigned int,那么它可能会执行您想要的操作。

      【讨论】:

        【解决方案5】:

        是的,正如@veer 指出的那样,使用int,您正在进行右算术移位,这对于将有符号数除以 2 的幂(以二进制补码表示)非常有用:

        通过将类型更改为unsigned int,它将变为右位移位,非常适合将无符号数除以 2 的幂(这是您的方案):

        Wikipedia Bitwise operation 上有一些很好的解释。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-09-27
          • 2019-05-26
          • 1970-01-01
          • 2011-05-19
          • 1970-01-01
          • 2013-12-01
          相关资源
          最近更新 更多