【问题标题】:Bit operation makes signed integer become unsigned位操作使有符号整数变为无符号
【发布时间】:2020-10-30 20:40:16
【问题描述】:

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

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

显然,结果是-1

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

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

代码 sn -p 打印 4294967295,uint32 类型可以容纳的最大数量。即使我在fmt.Printf("%d\n", int(c)) 中显式转换c,结果仍然是一样的。

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

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

【问题讨论】:

    标签: go casting bit signed


    【解决方案1】:

    这里的问题是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 直接分配给 int32 类型的值,因为该值会溢出;创建具有非法值的类型化常量(例如int32(0xffffffff))也是无效的。 Spec: Constants:

    typed 常量的值必须始终准确地使用常量类型的值representable

    所以这会产生编译时错误:

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

    但你可以这样做:

    var c int32 = -1
    

    你也可以这样做:

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

    【讨论】:

      猜你喜欢
      • 2018-10-28
      • 1970-01-01
      • 2015-12-28
      • 2013-09-01
      • 1970-01-01
      • 2016-12-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多