我正在调试一个问题,并发现以下代码段(已消毒)就是问题的原因。
uint64_t testflag = 0;
testflag &= ~(0x08ul); //bug
testflag &= ~(0x08l); //expected
我比较了生成的程序集并看到了这个
uint64_t testflag = 0;
804851e: c7 45 d8 00 00 00 00 movl $0x0,-0x28(%ebp)
8048525: c7 45 dc 00 00 00 00 movl $0x0,-0x24(%ebp)
testflag &= ~(0x08ul);
804852c: 83 65 d8 f7 andl $0xfffffff7,-0x28(%ebp)
8048530: 83 65 dc 00 andl $0x0,-0x24(%ebp)
testflag &= ~(0x08l);
8048534: 83 65 d8 f7 andl $0xfffffff7,-0x28(%ebp)
8048538: 83 65 dc ff andl $0xffffffff,-0x24(%ebp)
为什么NOT operator
的{{1}}会导致编译器使用较高字节而不是unsigned long
与0
进行对比。
我的gcc版本在64位计算机上为ffffffff
。
答案 0 :(得分:1)
假设32位unsigned long/long
...
uint64_t testflag;
0x08ul --> 00 00 00 08
~(0x08ul) --> FF FF FF F7
some_uint32_t = FF FF FF F7
testflag &= some_uint32_t;
testflag = testflag & some_uint32_t
testflag = testflag & (uint64_t) some_uint32_t
testflag = testflag & (uint64_t) FF FF FF F7 (or 4,294,967,288)
testflag = testflag & 00 00 00 00 FF FF FF F7
将32位无符号转换为uint64_t
只需0扩展。
现在使用~(0x08l)
0x08l --> 00 00 00 08
~(0x08l) --> FF FF FF F7
some_int32_t = FF FF FF F7
testflag &= some_int32_t;
testflag = testflag & some_int32_t
testflag = testflag & (uint64_t) some_int32_t
testflag = testflag & (uint64_t) FF FF FF F7 (or - 8)
testflag = testflag & FF FF FF FF FF FF FF F7 (or 18,446,744,073,709,551,608)
-8作为uint64_t
几乎是uint64_t
的最大值
使用2的补码,结果是OP的long
的符号位被扩展。 @Marc Glisse