《The Go Programming Launage》(Go语言圣经)无类型常量:

我的理解:Go的基础类型有:整数:int8、int16、int32、int64,浮点数:float32、float64,复数:complex64、complex128,字符:byte(1字节)、rune(4字节);当给出形如"const EiB = 1<<60"的常量声明,即常量声明没有显式给出类型,则:1、当常量表达式的值能够使用内置的最大类型(比如int64)存储时,Go编译器会使用该最大类型存储常量,而不是对常量表达式值使用能容纳得下的最小数据类型存储,比如下面的1<<62与1<<6。并且reflect.TypeOf()与unsafe.Sizeof()都能正确返回常量的类型(虽然整数常量总是返回int,需要与大小一起确定)与大小;2、当常量表达式的值不能使用内置的最大类型存储时,Go编译器将使用最少256位(书中说的)最多512位比特(实验得出的,如下)的“无类型”存储该常量值,力求能精确表示,如果是整数常量,只要在512位比特能表示的范围内,是能够精确存储并取值的,但不能使用reflect.TypeOf()与unsafe.Sizeof()取类型与大小;
//2、未明确类型的常量
//未明确具体类型,编译器为之提供至少256位至多512位比特,力求精确表示
// const inte2 = 1 << 512 //./hello.go:512:18: shift count too large: 512
const inte3 = 1 << 511
const inte4 = 1 << 501
fmt.Printf("%d\n", inte3/inte4) //1024
// fmt.Printf("reflect.TypeOf(1<<62) is %s \n", reflect.TypeOf(inte3)),报错
//inte3 (untyped int constant 6703903964971298549787012499102923063739682910296196688861780721
//860882015036773488400937149083451713845015929093243025426876941405973284973216824503042048) overflows int
// fmt.Printf("unsafe.Sizeof(1<<62) is %d \n", unsafe.Sizeof(inte3)),报错
//inte3 (untyped int constant 6703903964971298549787012499102923063739682910296196688861780721
//860882015036773488400937149083451713845015929093243025426876941405973284973216824503042048) overflows int
//上面报错成功给出了1<<511的值,说明1<<511有被正确存储,只不过不能用reflect.TypeOf()取类型或者unsafe.Sizeof()取内存大小
// fmt.Printf("%d \n", inte3)
//inte3 (untyped int constant 6703903964971298549787012499102923063739682910296196688861780721
//860882015036773488400937149083451713845015929093243025426876941405973284973216824503042048) overflows int
//当然,打印输出值也是不行的,超过了int64。能存储和参与计算(并且计算结果,作为临时变量,不能超出int64)是一回事,但不能用来打印输出
const inte5 = 1 << 62
fmt.Printf("reflect.TypeOf(1<<62) is %s \n", reflect.TypeOf(inte5)) //int
fmt.Printf("unsafe.Sizeof(1<<62) is %d \n", unsafe.Sizeof(inte5)) //8,用8个字节表示,int64,确实用得上这么大
const inter = 1 << 6
fmt.Printf("reflect.TypeOf(1<<6) is %s \n", reflect.TypeOf(inter)) //int
fmt.Printf("unsafe.Sizeof(1<<6) is %d \n", unsafe.Sizeof(inter)) //8,还是用8个字节,
//用int8其实就可以的,说明这里常量类型的反推总是按最大的int64来的
3、不指定类型的变量是严格不能超过反推的可能最大类型(比如int64)的最大值的,但也不会根据值“量身定制适合的最小数据类型”
4、为变量或常量指定类型总是准确的
//3、未明确类型的变量
//如果超出潜在最大类型(int64)的最大值将报错,
// var inte9 = 1 << 63 //1 << 63 (untyped int constant 9223372036854775808) overflows int
var inte10 = 1 << 62
fmt.Printf("reflect.TypeOf(1<<62) is %s \n", reflect.TypeOf(inte10)) //int
fmt.Printf("unsafe.Sizeof(1<<62) is %d \n", unsafe.Sizeof(inte10)) //8,用8个字节表示,int64,确实用得上这么大
var inter2 = 1 << 6
fmt.Printf("reflect.TypeOf(1<<6) is %s \n", reflect.TypeOf(inter2)) //int
fmt.Printf("unsafe.Sizeof(1<<6) is %d \n", unsafe.Sizeof(inter2)) //8
//用int8其实就可以的,说明这里变量类型的反推总是按最大的int64来的
//1、为变量或常量指定类型总是准确的
var inte7 uint8 = 1 << 7
fmt.Printf("unsafe.Sizeof(1<<7) is %d \n", unsafe.Sizeof(inte7)) //1
var inte8 uint16 = 1 << 15
fmt.Printf("unsafe.Sizeof(1<<15) is %d \n", unsafe.Sizeof(inte8)) //2
const inte6 uint32 = 1 << 31
fmt.Printf("unsafe.Sizeof(1<<31) is %d \n", unsafe.Sizeof(inte6)) //4
const inte9 uint64 = 1 << 63
fmt.Printf("unsafe.Sizeof(1<<63) is %d \n", unsafe.Sizeof(inte9)) //8

本文探讨了Go语言中无类型常量的存储机制及其特点。详细分析了不同大小的无类型常量如何被Go编译器处理,并讨论了在特定情况下这些常量的表现形式及限制。
737

被折叠的 条评论
为什么被折叠?



