无符号整数溢出

时间:2014-03-16 22:32:07

标签: go

关于无符号整数溢出的

Go spec say

  

对于无符号整数值,操作+, - ,*和<<是   计算模2n,其中n是无符号整数的位宽   类型。松散地说,这些无符号整数运算丢弃率很高   溢出后的位,程序可能依赖于''

我尝试测试它,但结果不一致 - http://play.golang.org/p/sJxtSHbigT

package main

import "fmt"

func main() {
    fmt.Println("test")
    var num uint32 = 1 << 35
}

这给出错误:

prog.go:7: constant 34359738368 overflows uint32
 [process exited with non-zero status]

但根据规范应该没有错误,而是我应该看到0。

2 个答案:

答案 0 :(得分:6)

您引用的规范特指&#34;操作+, - ,*和&lt;&lt;&#34;的结果。您正在尝试定义一个常量,而不是查看其中一个操作的结果。

您也无法使用这些超大值来输入这些操作。编译器不会为你包装任何值;这只是那些操作的运行时行为。

package main

import "fmt"

func main() {
    var num uint32 = 1 + 1 << 35
    fmt.Printf("num = %v\n", num)
}
prog.go:6: constant 34359738369 overflows uint32
 [process exited with non-zero status]

这是一个有趣的例子。

var num uint32 = (1 << 31) + (1 << 31)
fmt.Printf("num = %v\n", num)
prog.go:6: constant 4294967296 overflows uint32
 [process exited with non-zero status]

在这种情况下,编译器尝试在编译时评估(1 << 31) + (1 << 31),产生常量值4294967296,这个值太大而不适合。

var num uint32 = (1 << 31)
num += (1 << 31)
fmt.Printf("num = %v\n", num)
num = 0

在这种情况下,添加是在运行时执行的,并且值会像您期望的那样包围。

答案 1 :(得分:3)

那是因为1 << 35是一个无类型的常量表达式(它只涉及数值常量)。在您指定之前,它不会成为uint32。 Go禁止你为一个变量分配一个常量表达式,这个表达式会溢出它,因为这样的东西几乎肯定是无意的。