应用于无符号类型的一元减号运算符

unary minus operator applied to unsigned type

我正在阅读 wikipedia 关于 De Bruijn 序列的内容,但我的问题对这篇文章没有帮助,但解决了 msvc 编译器警告:

warning C4146: unary minus operator applied to unsigned type, result still unsigned

这是来自维基百科 link 的代码,它会产生此警告:

unsigned int v;   
int r;           
static const int MultiplyDeBruijnBitPosition[32] = 
{
  0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 
  31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
r = MultiplyDeBruijnBitPosition[((uint32_t)((v & -v) * 0x077CB531U)) >> 27];

警告在(v & -v)部分产生。

我还不能 100% 确定(还)它是如何工作的我只知道我需要它但是我的项目设置为在 W4 上干净地编译,这个很烦人,我应该如何继续解决这个问题在这里警告?

我们可以在这里使用 UINT_MIN 技巧吗?我没有尝试任何东西,因为我不想以函数的错误结果告终。

我的理解是 v & -v 应该提取特定位。

v & -v是为了提取lsb的值:

#include<iostream>
#include<bitset>
int main() {
    for(unsigned i = 1; i < 21; ++i) {
        std::cout <<std::bitset<8>(i)<<": ";
        std::cout<<i<<": "<<(i & -i)<<"\n";
    }
    return 0;
}


00000001: 1: 1
00000010: 2: 2
00000011: 3: 1
00000100: 4: 4
00000101: 5: 1
00000110: 6: 2
00000111: 7: 1
00001000: 8: 8
00001001: 9: 1
00001010: 10: 2
00001011: 11: 1
00001100: 12: 4
00001101: 13: 1
00001110: 14: 2
00001111: 15: 1
00010000: 16: 16
00010001: 17: 1
00010010: 18: 2
00010011: 19: 1
00010100: 20: 4

二进制补码中的无符号类型 -v 可以用

伪造
~v + 1