为什么不能将 int64 的最小值存储到 uint64 中?



理论上int64适合uint64,当然它们的数值会有所不同,因为int64上的第一个位是为符号保留的,但是为什么我不能做这个转换?这对我来说似乎是有效的

import (
"fmt"
"math"
)
func main() {
var randomNum uint64 = math.MinInt64
fmt.Println(randomNum)
}

收益率错误

constant -9223372036854775808 overflows uint64

这里的math.MinInt64-9223372036854775808,技术上是一个63位加号的数字。

我主要研究这个,因为我想将8 bytes转换回具有适当符号的int64,但到目前为止,我只看到返回uint64

的函数
binary.LittleEndian.Uint64(bytesArrays[0:8])

这个"转换"的原因不起作用,是因为你的程序中没有转换。赋值不隐式地执行转换(接口类型除外)。

参见控制常量值赋值的可赋值规则:

如果满足下列条件之一,值x可赋值给类型为T的变量("x可赋值给T"):

  • x的类型与t相同
  • x是一个无类型常量,可以用t类型的值表示。

在这种情况下,math.MinInt64是一个无类型的常量,但它不能用uint64类型的值表示,因为它是这样定义的:

uint64所有无符号64位整数(0 ~ 18446744073709551615)的集合

负64位整数和无符号64位整数之间的转换是可能的,但是你需要一个真正的转换。然而,由于一个熟悉的规则,您仍然不能直接转换常量值:

如果x可以用T表示,则常数值x可以转换为类型T

因此,正确的方法是首先将数字赋值给一个非常量值:
x := int64(math.MinInt64)
y := uint64(x)
fmt.Println(y)

操场上联系

int64 fits确实适合uint64,但问题中的代码不是这样做的。这段代码为常数math赋值。MinInt64转换为uint64变量randomNum。编译器报告一个错误,因为常量不能用uint64表示。

先赋值给一个变量,这样就不适用常量的规则了:

x := int64(math.MinInt64)
var randomNum = uint64(x)
fmt.Println(randomNum)

谁说你不行?编译器会这么说。但是编译器意味着你不能把-9223372036854775808放入uint64变量中,这是真的;你需要把位模式,作为int64,表示-9223372036854775808,但表示值,它将被视为uint64uint64:

var randomNum uint64 = math.MinInt64 + math.MaxUint64 + 1

效果很好,当然也可以像GastroHealth展示的那样。

我主要研究这个,因为我想将[8]字节转换回具有适当符号的int64,但到目前为止,我只看到返回uint64的函数(例如binary.LittleEndian.Uint64)。

我们做显而易见的:

signed := int64(v ^ 0x8000000000000000 - 0x8000000000000000)

(好吧,一旦你看到它几次就很明显了。)

在这里查看完整的示例(我使用大端序,我更喜欢人类使用它)。注意,您可以在这里执行signed := int64(v);在没有变量的情况下,翻转减法技巧很适合用于表达式。

最新更新