Go 中移位和除法的意外输出:为什么 a 和 b 不同?

问题描述 投票:0回答:1

我有一个Go程序,它对字符串常量的长度执行位移和除法运算,但输出不是我所期望的。这是代码:

package main

import "fmt"

const s = "123456789" // len(s) == 9

// len(s) is a constant expression,
// whereas len(s[:]) is not.
var a byte = 1 << len(s) / 128
var b byte = 1 << len(s[:]) / 128

func main() {
    fmt.Println(a, b) // outputs: 4 0
}

在此程序中,a 和 b 使用涉及移位和除法的类似表达式计算。然而,a 和 b 的输出分别是 4 和 0,这似乎违反直觉,因为这两个操作都涉及相同的字符串长度和相似的算术。有人能解释一下为什么a和b产生不同的结果吗?

  • 在这种情况下除以 128 和位移位有什么作用?
  • 为什么 len(s[:]) 不被视为常量表达式,这对计算有何影响?

如果您能深入了解这些表达式如何以不同的方式求值以及它们为何会在 Go 中产生不同的输出,我将不胜感激。

go
1个回答
0
投票

第一个示例是常量移位操作,将在“const”空间中执行,结果将转换为

byte
(因为它适合一个字节)。

第二个例子是非常量移位运算,所以根据规范,

1
会先转换为
byte
,然后将移位和除法作为
byte
值进行(移位结果不适合
byte
,因此结果将是
0
),除以
128
将再次得到
0

来自规范的相关部分:操作员:

移位表达式中的右操作数必须具有 整数类型 (Go 1.13) 或者是可由类型

uint
的值表示的无类型常量。如果非常量移位表达式的左操作数是无类型常量,则它首先会隐式转换为移位表达式仅由其左操作数替换时所假定的类型。

参见相关:Golang 移位运算符转换

© www.soinside.com 2019 - 2024. All rights reserved.