踩了个陷阱: Python bitwise ~ vs. C bitwise ~

2017-06-19 16:45:36 +08:00
 justou

有如下 C 代码:

#include <stdio.h>

int main()
{
    int x = 0x87654321;
    int mask = 0xFF;                            

    printf("0x%08x\n", ~mask);
    printf("0x%08x\n", x & mask);    
    printf("0x%08x\n", x ^ ~mask);   
    printf("0x%08x\n", x | mask); 
    return 0;
}

输出:

0xffffff00
0x00000021
0x789abc21
0x876543ff

改成对应的 python 代码:

x = 0x87654321
mask = 0xFF
print("0x%08x" % (~mask))
print("0x%08x" % (x & mask))
print("0x%08x" % (x ^ ~mask))
print("0x%08x" % (x | mask))

输出:

0x-0000100
0x00000021
0x-876543df
0x876543ff

请问 python 输出与 C 输出不一致的原因是什么,能否修改 python 代码使其与 C 输出一致?

1956 次点击
所在节点    Python
6 条回复
pright
2017-06-19 17:28:25 +08:00
import ctypes

print("0x%08x" % (ctypes.c_uint(~mask).value))
enenaaa
2017-06-19 17:48:12 +08:00
好像是被当成有符号数打印了。
试一下 &0xffffffff。这样
print("0x%08x" % ((~mask)&0xffffffff))
popstk
2017-06-19 17:54:49 +08:00
<code>def foo(n, size=32):
return ((1<<size)-1)&n


x = 0x87654321
mask = 0xFF
print("0x%08x" % foo(~mask))
print("0x%08x" % foo(x & mask))
print("0x%08x" % foo(x ^ ~mask))
print("0x%08x" % foo(x | mask))
</code>

https://wiki.python.org/moin/BitwiseOperators
NoAnyLove
2017-06-20 00:48:15 +08:00
因为 Python 的 int 是无限长度的,如果对一个正整数取反,会变成负数,你可以认为符号位是无限长度的 1:

```
>>> mask = 0xFF
>>> bin(mask)
'0b11111111'
>>> ~mask
-256
>>> bin(~mask)
'-0b100000000'
```

`bin(~mask)`返回结果'-0b100000000',前面的`-0`就是相当于无限长度的符号位,如果用 Two ‘ s Complement 来表示就全是 1.

解决这个问题也很简单,将结果按位与 0xFFFFFFFF (刚好 32 位 bit )运算,就可以消除掉超过 32 位的无限长度的符号位。

```
>>> ~mask & 0xFFFFFFFF
4294967040
>>> hex(_)
'0xffffff00'
```
justou
2017-06-20 11:23:05 +08:00
感谢楼上各位,4L 给了个很好的解释
pright
2017-06-20 14:10:35 +08:00
这里不一致的原因其实就是 C 的 printf 的%x 对应的是 unsigned hexadecimal integer,而 python 的 print 的%x 对应的是 signed hexadecimal integer。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/369580

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX