各位大佬,在 go 中一个 const 声明超出 uint64 最大值后这个数的类型是什么?

103 天前
 nevermoreluo

初学 go ,看教程 const的时候,发现 Big = 1 << 100 明显超出基础类型 uint64 了,于是想看下 Big 是什么类型

但是打印都 overflow 了遂有此疑问


const (
    // 将 1 左移 100 位来创建一个非常大的数字
    // 即这个数的二进制是 1 后面跟着 100 个 0
    Big = 1 << 100
    // 再往右移 99 位,即 Small = 1 << 1 ,或者说 Small = 2
    Small = Big >> 99
)

func main() {
    // cannot use Big (untyped int constant 1267650600228229401496703205376) as int value in argument to fmt.Printf (overflows)
    fmt.Printf("T of Big %T\n", Big)
    // cannot use Big (untyped int constant 1267650600228229401496703205376) as int value in argument to reflect.TypeOf (overflows)
    fmt.Println("T of Big ", reflect.TypeOf(Big))

}
2276 次点击
所在节点    Go 编程语言
16 条回复
uiosun
103 天前
dapang1221
103 天前
鉴定为计算机原理没学好,重新看下书
nevermoreluo
103 天前
@uiosun
这篇我看了 但是还是没搞明白这个 Big 到底属于什么类型。
或者说我的问题应该改为
对于 go 来说他既然可以运算 Small 的值,那么在运行时他拿什么类型处理 Big 这个超出他规定基础类型的对象的?
pkoukk
103 天前
你没声明它的类型它哪来的类型?
aminobody
103 天前
@nevermoreluo #3 `The default type for the untyped constant Big is int.`
nevermoreluo
103 天前
@aminobody 1 << 100 超出 int 的存储范围了
nevermoreluo
103 天前
看到这个
https://stackoverflow.com/questions/38982278/how-does-go-perform-arithmetic-on-constants/38982889#38982889

大概理解了,在编译时把这个值处理了,运行时就不用考虑了,所以企图打印他会在编译时报错,但是计算可以。
谢谢各位大佬
otakustay
103 天前
超出范围就溢出呗,溢出又不会改变类型
zonyitoo
103 天前
nevermoreluo
103 天前
@zonyitoo
因为没有声明类型,先入为主的以为跟 c++的 auto 一样编译时推断了。
看起来这个 const 在 go 里面有很多细节处理,学习了,谢谢大佬。
lasuar
103 天前
默认一律是 int 类型,数据溢出按溢出处理,搜索 [编程语言整型溢出] ,
nevermoreluo
103 天前
@lasuar
应该不是的,他并没有做溢出处理,而是在编译时精确的计算了。
你可以简单打印以下这几个值看看。如果按他最大基础类型 uint64 算的话,溢出处理,和实际结果不对。

const Big = 18446744073709551617;
const OtherBig = Big + 1;
const BigI = OtherBig - 3;
lasuar
103 天前
这里因为是常量方式的声明,所以直接编译失败了。类型默认 INT ,没有如果。
wudanyang
103 天前
编译的时候就出错了,还有啥类型
uiosun
103 天前
@nevermoreluo

这篇问答里的 comment 有更多文章可以阅读,其中以官方文档为例:

> But in Go, a constant is just a simple, unchanging value, and from here on we’re talking only about Go.

按我理解,常量只是作为一个值,当你需要推断它的类型时,Go 才会尝试推断它的类型——推断。

所以,你的报错很正常,正是反映了这样的规则:cannot use Big (untyped int constant 1267650600228229401496703205376) as int value in argument to fmt.Printf (overflows)
wisej
102 天前
来回答你 append 里的问题:

1. Big 常量,底层用的 math/big 包
2. precision 有极限,golang 自带的 compiler 设的 512bit (不过根据 spec ,integer constants 不小于 256 即可)。1<<511 没问题, 1<<512 就报 overflow 了

这些答案可以在 src/go/constant/value.go 源码找到

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1059330

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX