奇怪的位操作导致 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=0x20
和r8=0xFFFFFFFF
指令后,我们还有r8=0xFFFFFFFF
我对 x86-64 汇编的了解很差,但这条指令应该是一个无符号移位,所以为什么结果不是 0?
我正在使用 mingw-gcc x86-64 4.9.1
在编译器上调用 -Wall
,您将遇到 -Wshift-count-overflow
问题,因为您使用 32 进行移位,这是 unsigned int 的大小。现在你可以做一件事只是为了了解它。将 32 更改为 31 并编译。然后对比生成的程序集就知道哪里出了问题
最简单的解决方法是对 all1
和 result
使用 long
数据类型。
在 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=0x20
和r8=0xFFFFFFFF
指令后,我们还有r8=0xFFFFFFFF
我对 x86-64 汇编的了解很差,但这条指令应该是一个无符号移位,所以为什么结果不是 0?
我正在使用 mingw-gcc x86-64 4.9.1
在编译器上调用 -Wall
,您将遇到 -Wshift-count-overflow
问题,因为您使用 32 进行移位,这是 unsigned int 的大小。现在你可以做一件事只是为了了解它。将 32 更改为 31 并编译。然后对比生成的程序集就知道哪里出了问题
最简单的解决方法是对 all1
和 result
使用 long
数据类型。