奇怪的位操作导致 C++/反汇编?

Strange bit operation result in C++ / disassembly?

在 C++ 函数中,我有以下变量:

uint32_t buf = 229;  //Member variable
int bufSize = 0;     //Member variable
static constexpr const uint32_t all1 = ~((uint32_t)0);

这行代码:

uint32_t result = buf & (all1 >> (32-bufSize ));

那么result的值为229,无论是通过控制台输出,还是通过gdb调试。期望值当然是 0,任何试图制作一个最小示例重现问题的尝试都失败了。

于是我去反汇编,一步步执行。位移操作在这里:

0x44c89e  <+0x00b4>        41 d3 e8                 shr    %cl,%r8d

调试器寄存器显示在指令之前,rcx=0x20r8=0xFFFFFFFF

指令后,我们还有r8=0xFFFFFFFF

我对 x86-64 汇编的了解很差,但这条指令应该是一个无符号移位,所以为什么结果不是 0?

我正在使用 mingw-gcc x86-64 4.9.1

在编译器上调用 -Wall,您将遇到 -Wshift-count-overflow 问题,因为您使用 32 进行移位,这是 unsigned int 的大小。现在你可以做一件事只是为了了解它。将 32 更改为 31 并编译。然后对比生成的程序集就知道哪里出了问题

最简单的解决方法是对 all1result 使用 long 数据类型。