【问题标题】:Shifting 64 bit value left by 64 bits in C++ giving weird results [duplicate]在 C++ 中将 64 位值左移 64 位给出奇怪的结果 [重复]
【发布时间】:2012-08-05 14:52:59
【问题描述】:

可能重复:
64bit shift problem

我在 Windows 8 64 位上使用 Visual Studio 2012,在调试模式下以 x64 为目标,使用 AMD Phenom II。
所以基本上...

uint64_t Foo = 0xFFFFFFFFFFFFFFFF << 64;//Foo is now 0x0000000000000000
uint64_t Derp = 64;
uint64_t Bar = 0xFFFFFFFFFFFFFFFF << Derp;//Foo is now 0xFFFFFFFFFFFFFFFF

使用较低的值(例如 63)可以恢复正常行为。
为什么会发生这种情况,我该如何解决?

更新:我切换到发布模式。瞧,问题消失了,都返回了 0。但问题仍然处于调试模式,这是我调试代码所需的位置。

【问题讨论】:

    标签: c++ 64-bit bit-manipulation shift


    【解决方案1】:

    如果移位大于或等于位宽的值,则移位操作具有未定义的行为。

    来自 C++11 草案中的第 5.8 节 p1:

    操作数应为整数或非范围枚举类型,并执行整数提升。 结果的类型是提升的左操作数的类型。如果正确的操作数,则行为未定义 为负数,或大于或等于提升的左操作数的位长度。

    【讨论】:

    • 他们为什么要那样做?它在Java中也是一样的,没有意义,如果>>应该设置为零,如果>>应该设置为最大值
    • @gia 标准机构通常决定使行为未定义,以便编译器实现者不必生成昂贵(缓慢)的代码来处理边缘情况。
    • 它可能会出现在芯片上或其他东西上,我的意思是最终我还是要进行检查:P
    • @gia 如果参数是文字常量,则不需要检查。
    • 是的,在我的情况下它不是文字,我只是添加了检查,代码不可读
    【解决方案2】:

    我相信 C++ 中未定义整数大小或更大的移位。

    您的第一个示例在编译时进行评估,因为它只涉及常量。您的第二个示例由处理器在运行时计算。

    您可以将班次分成两部分:

    uint64_t Bar = 0xFFFFFFFFFFFFFFFF << (Derp / 2);
    Bar <<= Derp - (Derp / 2);
    

    【讨论】:

      猜你喜欢
      • 2012-04-20
      • 1970-01-01
      • 1970-01-01
      • 2014-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-27
      相关资源
      最近更新 更多