首页 > 解决方案 > 位操作使有符号整数变为无符号

问题描述

计算机使用二进制补码来存储整数。比如说,对于 int32 签名,0xFFFFFFFF 代表“-1”。根据这个理论,用 C 语言编写这样的代码将有符号整数初始化为 -1 并不难;

int a = 0xffffffff;
printf("%d\n", a);

显然,结果是-1

但是,在 Go 中,相同的逻辑转储不同。

a := int(0xffffffff)
fmt.Printf("%d\n", c)

代码片段打印4294967295uint32 类型可以容纳的最大数量。即使我c明确地投入fmt.Printf("%d\n", int(c)),结果仍然是一样的。

当对有符号整数也施加一些位操作时,也会发生同样的问题,使有符号变为无符号。

那么,在这种情况下,Go 会发生什么?

标签: gocastingbitsigned

解决方案


这里的问题是大小int不固定,它取决于平台。它可能是 32 位或 64 位。在后一种情况下,分配0xffffffff给它等同于分配4294967295给它,这就是您看到的打印内容。

现在,如果您将该值转换为int32(32 位),您将获得-1

a := int(0xffffffff)
fmt.Printf("%d\n", a)

b := int32(a)
fmt.Printf("%d\n", b)

这将输出(在Go Playgroung上尝试):

4294967295
-1

另请注意,在 Go 中,无法0xffffffff直接分配 typeint32的值,因为该值会溢出;创建具有非法值的类型化常量(例如int32(0xffffffff). 规格:常数:

类型化常量的值必须始终可以由常量类型的值准确表示

所以这给出了一个编译时错误:

var c int32 = 0xffffffff // constant 4294967295 overflows int32

但你可以简单地做:

var c int32 = -1

你也可以这样做:

var c = ^int32(0) // -1

推荐阅读