这个位移位在这个例子中是如何工作的?

How is this bitshifting working in this example?

我正在阅读 golang.org 上的 go 教程,我遇到了一个我部分理解的示例...

MaxInt uint64     = 1<<64 - 1

现在我明白这是将位向左移动 64 位,这将使它成为 1 后跟 64 个 0。

我的问题是为什么这是 64 位数字可以达到的最大整数。最大整数不是 111111111....(until the 64th 1) 而不是 100000...(until the 64th one) 吗?

这里发生了什么,一步一步:

  1. 取1.

  2. 左移64位。这很棘手。结果实际上需要 65 位来表示——即 1 后跟 64 个零。既然我们在这里计算一个 64 位值,为什么这甚至可以编译而不是溢出到 0 或 1 或产生编译错误?

  3. 之所以有效,是因为 Go 中用于计算常量的算法有点神奇 (https://blog.golang.org/constants),因为它与正在计算的命名常量的类型无关。你可以说 foo uint8 = 1<<415 / 1<<414 并且 foo 现在是 2.

  4. 减1。这让我们回到64位数字,因为它实际上是11....1(64次),这确实是uint64的最大值。如果没有这一步,编译器会抱怨我们试图将 65 位值塞入 uint64.

  5. 将常量命名为 MaxInt 并为其指定类型 uint64。成功!

用于计算常量的魔法算法仍然有局限性(很明显)。大于 500 次左右的偏移会产生有趣的命名 stupid shift 错误。