计算机使用二的补码来存储整数。例如,对于有符号的int32,0xFFFFFFFF表示"-1"。根据这一理论,用C编写这样的代码将有符号整数初始化为-1并不困难;
int a = 0xffffffff;
printf("%dn", a);
显然,结果是-1
。
但是在Go中,相同的逻辑转储方式不同。
a := int(0xffffffff)
fmt.Printf("%dn", c)
代码片段打印4294967295
,这是uint32类型可以容纳的最大数量。即使我在fmt.Printf("%dn", int(c))
中显式地强制转换c
,结果仍然相同。
当一些位运算也被强加在有符号整数上时,同样的问题也会发生,使有符号变成无符号。
那么,在这种情况下Go会发生什么呢?
这里的问题是int
的大小不是固定的,它依赖于平台。它可以是32位或64位。在后一种情况下,将0xffffffff
分配给它相当于将4294967295
分配给它,这就是您看到的打印内容。
现在,如果您将该值转换为int32
(32位(,您将获得-1
:
a := int(0xffffffff)
fmt.Printf("%dn", a)
b := int32(a)
fmt.Printf("%dn", b)
这将输出(在Go PlayGrong上尝试(:
4294967295
-1
还要注意,在Go中,不可能将0xffffffff
直接分配给int32
类型的值,因为该值会溢出;也不能创建具有非法值的类型化常量(例如int32(0xffffffff)
(。规格:常数:
类型常量的值必须始终由常量类型的值精确表示。
所以这会产生编译时错误:
var c int32 = 0xffffffff // constant 4294967295 overflows int32
但你可以简单地做:
var c int32 = -1
你也可以这样做:
var c = ^int32(0) // -1