小编典典

当你写

1<<64
1int64

常量表达式总是精确地求值;中间值和常量本身可能需要比该语言中任何预声明类型支持的精度大得多的精度。

因此,常量文字会在编译时进行评估,因为它不是语言实现的特定类型,所以它可能非常大。

下面实际上会给出一个溢出错误:

var i int64
i = 1<<65 - 1
int64

在此处阅读有关此内容的更多信息。

i = 65

移位表达式中的右操作数必须具有无符号整数类型,或者是可以转换为无符号整数类型的无类型常量。如果 非恒定移位表达式
左操作数是未类型化的常数,则首先将其转换为假定移位表达式被其左操作数单独替换时所假定的类型

上面的膨胀部分与您的代码有关。考虑下面的代码:

a := 66
var j uint64 = 1<<uint64(a) - 1
1uint64
uint64(1)<

请注意,根据语言规范,此行为与溢出并不相同。同样,只要正确的运算符不是常量表达式,语言限制就可以进行任意多的移位。因此,例如,这将起作用:

a := 6666
var j uint64 = 1<<uint64(a) - 1 // non-constant shift expression
1uint64
1uint64
var j uint64 = 1<<uint64(66) - 1 // overflow. Note that uint64(64)
fmt.Println(j)                   // is typed, but it's still a constant