问题描述
我找到了一些 odd looking code in the math/big library,但不明白它是如何工作的。我已将常量提取到示例中:
package main
import (
"fmt"
"math/bits"
)
const (
_S = _W / 8 // word size in bytes
_W = bits.UintSize // word size in bits
_B = 1 << _W // digit base
_M = _B - 1 // digit mask
)
func main() {
fmt.Println(_S,_W,_B,_M)
}
返回错误:
bug/example.go:17:13: constant 18446744073709551616 overflows int
bug/example.go:17:13: constant 18446744073709551615 overflows int
明确地说,我明白为什么这段代码不起作用。我感兴趣的是知道为什么在标准库中使用此常量时不会发生此错误?
我认为它可能会被延迟评估(即 _B - 1
),但我可以看到它是 literally used in tests。那么这里会使用什么值?
解决方法
“常量 18446744073709551616 溢出 int?” -- 是的。
int
取决于架构,至少为 32 位。 int32
最大值为 2147483647
和 int64
最大值为 9223372036854775807
,两者都不足以容纳 18446744073709551615
。
https://golang.org/ref/spec#Constants
数字常量代表任意精度的精确值,并且做 不溢出。因此,没有常数表示 IEEE-754 负零、无穷大和非数字值。
常量可以通过常量声明显式指定类型或 转换,或隐式用于变量声明或 赋值或作为表达式中的操作数。 这是一个错误,如果 常量值不能表示为各自的值 类型。
在您的情况下,根据使用它的表达式,常量值的类型为 int
,并且由于它不能由该类型表示,因此会导致错误。
如果您希望代码能够编译,您可以将常量转换为 float64
(或 uint
,在 _M
的情况下)。
package main
import (
"fmt"
"math/bits"
)
const (
_S = _W / 8 // word size in bytes
_W = bits.UintSize // word size in bits
_B = 1 << _W // digit base
_M = _B - 1 // digit mask
)
func main() {
fmt.Println(_S,_W,float64(_B),uint(_M))
}
https://play.golang.org/p/AVT5FPHinT3
更多信息请参见:Does Go compiler's evaluation differ for constant expression and other expression