I was taking a look at A Tour of Go and I was confused by something in their basic-types.go example:
MaxInt uint64 = 1<<64 - 1
Shouldn't shifting a 1 64 positions to the left in an unsigned 64 bit integer cause overflow (a.k.a. shifting a bit past the MSB)?
However, the compiler doesn't complain until the line is changed to:
MaxInt uint64 = 1<<65 - 1
./basic-types.go:5: constant 36893488147419103231 overflows uint64
If I write some code to iterate over left shifts of varying lengths, including shifting by 65 as in the above example that causes the compiler to barf, I see two things:
It behaves as I expected, in that
1<<63places the 1 in the MSB possible for an uint64It doesn't overflow anymore (huh?!?!)
code:
package main
import "fmt"
func main() {
for i := 60; i < 66; i++ {
var j uint64 = 1 << uint64(i) - 1
fmt.Printf("%2d | %64b | %#18x
", i, j, j)
}
output:
60 | 111111111111111111111111111111111111111111111111111111111111 | 0xfffffffffffffff
61 | 1111111111111111111111111111111111111111111111111111111111111 | 0x1fffffffffffffff
62 | 11111111111111111111111111111111111111111111111111111111111111 | 0x3fffffffffffffff
63 | 111111111111111111111111111111111111111111111111111111111111111 | 0x7fffffffffffffff
64 | 1111111111111111111111111111111111111111111111111111111111111111 | 0xffffffffffffffff
65 | 1111111111111111111111111111111111111111111111111111111111111111 | 0xffffffffffffffff