问题描述
几周前才开始学习Go,这种行为令我非常困惑。
var n int8 = -128
n /= -1
fmt.Println(n)
n *= -1
fmt.Println(n)
以上code都将输出-128
。我还尝试了-64 * -2
,这也导致了-128
。
-128
的值是否特殊,这意味着int 溢出?
解决方法
这不是在溢出时使用的特殊值,它只是一个带符号的8位整数的最小值(有效范围为[-128,128)
,表示包括-128,但不包括-128)。 / p>
在简单的情况下,例如增加最大值(例如:int8(127) + 1
),您会使整数溢出并以最小值结尾。
在Go语言中,这是完全可以接受的,正如spec
所述对于有符号整数,可以合法地使用+,-,*,/和
但是您的具体情况有所不同,这是由于取最大负值的2的补码会返回相同的值。
最简单的例子是这个例子:
var n int8 = -128
fmt.Println(-n)
// output -128
这是因为翻转所有位并加1将返回完全相同的内容:
// Start with -128
n = 1000 0000
// Flip bits:
n = 0111 1111
// Add 1:
n = 1000 0000
糟糕!这意味着-(-128) == -128
。
乘法和除法也是如此:-1 * (-128) == -128
。
在除法的情况下,某些语言的结果不确定。
Go spec并没有说明这种歧义,而是说明了这种特殊情况:
...如果红利x最大 x的int类型为负值,商q = x / -1等于 由于二进制补码整数溢出而导致x变为x(且r = 0)
您可以在Wikipedia上找到有关二进制补码算术的更多信息,该节专门介绍the most negative number。