假设我有这个号码 i = -6884376
。我如何将其称为无符号变量?像 (unsigned long)i
在 C 中。
原文由 Lior 发布,翻译遵循 CC BY-SA 4.0 许可协议
要获得与 C 转换等效的值,只需按位并使用适当的掩码即可。例如,如果 unsigned long
是 32 位:
>>> i = -6884376
>>> i & 0xffffffff
4288082920
或者如果它是 64 位:
>>> i & 0xffffffffffffffff
18446744073702667240
请注意,虽然这给了你在 C 中的值,但它仍然是一个带符号的值,因此任何后续计算都可能给出负结果,你将不得不继续应用掩码来模拟 32 或 64位计算。
这是可行的,因为尽管 Python 看起来将所有数字存储为符号和大小,但按位运算被定义为处理二进制补码值。 C 以二进制补码形式存储整数,但位数是固定的。 Python 按位运算符作用于二进制补码值,但就好像它们具有无限多的位数:对于正数,它们向左扩展到零为无穷大,但负数向左扩展为一。 &
运算符会将左边的一串变成零,只剩下适合 C 值的位。
以十六进制显示值可能会使这一点更清楚(我将 f 的字符串重写为表达式以表明我们对 32 位或 64 位感兴趣):
>>> hex(i)
'-0x690c18'
>>> hex (i & ((1 << 32) - 1))
'0xff96f3e8'
>>> hex (i & ((1 << 64) - 1)
'0xffffffffff96f3e8L'
对于 C 中的 32 位值,正数最高为 2147483647 (0x7fffffff),负数的最高位设置为 -1 (0xffffffff) 至 -2147483648 (0x80000000)。对于完全适合掩码的值,我们可以通过使用较小的掩码移除符号位然后减去符号位来反转 Python 中的过程:
>>> u = i & ((1 << 32) - 1)
>>> (u & ((1 << 31) - 1)) - (u & (1 << 31))
-6884376
或者对于 64 位版本:
>>> u = 18446744073702667240
>>> (u & ((1 << 63) - 1)) - (u & (1 << 63))
-6884376
如果符号位为 0,此逆过程将保持值不变,但显然它不是真正的逆过程,因为如果您以不适合掩码大小的值开始,那么这些位就会消失。
原文由 Duncan 发布,翻译遵循 CC BY-SA 3.0 许可协议
2 回答5.2k 阅读✓ 已解决
2 回答1.1k 阅读✓ 已解决
4 回答1.4k 阅读✓ 已解决
3 回答1.3k 阅读✓ 已解决
3 回答1.3k 阅读✓ 已解决
2 回答862 阅读✓ 已解决
1 回答1.7k 阅读✓ 已解决
假设:
(unsigned long)
你的 意思是 无符号 32 位整数,那么你只需要将
2**32 (or 1 << 32)
添加到负值。例如,将其应用于 -1:
假设 #1 意味着您希望 -1 被视为 1 位的实心字符串,而假设 #2 意味着您想要其中的 32 个。
但是,除了您之外,没有人可以说出您隐藏的假设是什么。例如,如果您有 1 的补码表示,那么您需要改为应用
~
前缀运算符。 Python 整数努力给出使用无限宽的 2 的补码表示的错觉(就像常规的 2 的补码,但具有无限数量的“符号位”)。要复制平台 C 编译器的功能,您可以使用
ctypes
模块:C 的
unsigned long
恰好是运行该样本的盒子上的 4 个字节。