2 回答
TA贡献1810条经验 获得超4个赞
如果你有这个:
var s uint = 33 fmt.Println(1 << s)
然后引用的部分适用:
如果非常量移位表达式的左操作数是无类型常量,则首先将其隐式转换为移位表达式单独由其左操作数替换时所假定的类型。
因为s
不是常量(它是变量),所以1 >> s
是非常量移位表达式。左操作数是1
一个无类型常量(例如int(1)
,将是一个类型化常量),因此它被转换为一个类型,如果表达式简单地1
代替1 << s
:
fmt.Println(1)
在上面,无类型常量1
将被转换为int
,因为这是它的默认类型。常量的默认类型在Spec: Constants:
无类型常量有一个默认类型,即常量在需要类型化值的上下文中隐式转换为的类型,例如,在没有显式类型的短变量声明中。
i := 0
无类型常量的默认类型分别为bool
、rune
、int
、float64
或complex128
,string
具体取决于它是布尔值、符文、整数、浮点数、复数还是字符串常量。
上述结果取决于体系结构。如果int
是 32 位,它将是0
. 如果int
是 64 位,它将是8589934592
(因为将位移动1
33 次会将其移出 32 位int
数字)。
在 Go 操场上,大小int
为 32 位(4 字节)。看这个例子:
fmt.Println("int size:", unsafe.Sizeof(int(0)))
var s uint = 33
fmt.Println(1 << s)
fmt.Println(int32(1) << s)
fmt.Println(int64(1) << s)
上面的输出(在Go Playground上试试):
int size: 4
0
0
8589934592
如果我在我的 64 位计算机上运行上面的应用程序,输出是:
int size: 8
8589934592
0
8589934592
请注意,如果您编写1 << 33
,那是不一样的,那不是一个非常量移位表达式,您的引用适用于:"the left operand of a non-constant shift expression"。1<<33
是一个常量移位表达式,在“常量空间”进行计算,结果将转换为int
不适合 32 位的int
,因此会出现编译时错误。它适用于变量,因为变量可能会溢出。常量不会溢出:
数值常量表示任意精度的精确值并且不会溢出。
从 转换为int16
只int8
保留最低 8 位。整数使用2 的补码格式表示,其中最高位是1
负数。
这在规范中有详细说明:转换:
在整数类型之间转换时,如果值为有符号整数,则将其符号扩展为隐式无限精度;否则为零扩展。然后将其截断以适合结果类型的大小。例如,如果
v := uint16(0x10F0)
,则uint32(int8(v)) == 0xFFFFFFF0
。转换总是产生有效值;没有溢出的迹象。
因此,当您将int16
值转换为 时int8
,如果源编号的1
位位置为 7(第 8 位),则结果将为负,即使源不是负数。类似地,如果源在位0
位置 7,结果将为正,即使源为负。
看这个例子:
for _, v := range []int16{4336, -129, 8079} {
fmt.Printf("Source : %v\n", v)
fmt.Printf("Source hex: %4x\n", uint16(v))
fmt.Printf("Result hex: %4x\n", uint8(int8(v)))
fmt.Printf("Result : %4v\n", uint8(int8(v)))
fmt.Println()
}
输出(在Go Playground上尝试):
Source : 4336
Source hex: 10f0
Result hex: f0
Result : -16
Source : -129
Source hex: ff7f
Result hex: 7f
Result : 127
Source : 8079
Source hex: 1f8f
Result hex: 8f
Result : -113
- 2 回答
- 0 关注
- 141 浏览
添加回答
举报