代码之家  ›  专栏  ›  技术社区  ›  Marc

C右移在我的程序中不能正确处理int类型

  •  1
  • Marc  · 技术社区  · 7 年前

    我在C中具有以下功能:

    int lrot32(int a, int n)
    {
        printf("%X SHR %d = %X\n",a, 32-n, (a >> (32-n)));
        return ((a << n) | (a >> (32-n)));
    }
    

    当我作为参数lrot32(0x8F5AEB9C,0xB)传递时,我得到以下结果:

    8F5AEB9C shr 21 = FFFFFC7A
    

    然而,结果应该是47A。我做错了什么?

    1 回复  |  直到 7 年前
        1
  •  4
  •   Antti Haapala -- Слава Україні    7 年前

    int 是有符号整数类型。 C11 6.5.7p4-5

    4结果 E1 << E2 E1 左移 E2 位位置;空出的位用零填充。[…]如果 E1 E2 可以在结果类型中表示,那么这就是结果值;否则

    5结果 E1 >> E2 E1 位位置。[…]如果 E2 . E1 具有符号类型和负值,结果值由实现定义。

    << ,如果移位值为负值,或移位后的正值不能在结果类型中表示(此处: ),行为未定义;假使 >> ,如果该值为负值,则结果为 .

    因此,在任何一种情况下,您都会得到至少取决于实现的结果,在左移位的情况下,更糟糕的是,可能取决于优化级别等等。严格一致性程序不能依赖于任何特定行为。


    GCC says :

    位运算符作用于值的表示,包括 在最高值位的正上方。 签名(>)&燃气轮机;作用于 符号扩展的负数。 [*]

    GCC不使用给定的纬度 未定义。 诊断此类病例。他们还被诊断为常数 表达式是必需的。

    [*]符号扩展在这里意味着符号位-即 1 F s在结果中。

    此外,GCC总是需要2的补码表示,所以如果您愿意 使用GCC,无论您针对哪种架构,这都是您会看到的行为。此外,将来有人可能会为您的代码使用另一个编译器,从而导致其他行为。


    也许你想用无符号整数- unsigned int 或者更确切地说,如果预期一定的宽度,那么例如 uint32_t


    另一个需要注意的是,并非所有的班次都是允许的。 C11 6.5.7 p3 :

    未定义