uint8与int8类型算术运算出现零值、负数结果的原因解析
Go中uint8/int8算术运算出现零值、负数的原因
这其实是Go语言中固定大小整数类型的溢出环绕行为导致的,咱们结合代码里的例子一步步拆解:
首先先明确两个类型的取值范围:
uint8:无符号8位整数,取值范围是0到255(也就是2^8 - 1)int8:有符号8位整数,用补码存储,取值范围是-128到127(最高位作为符号位,正数最大是2^7 -1,负数最小是-2^7)
1. uint8的运算分析
看这段代码:
var u uint8 = 255 fmt.Println(u, u+1, u*u) // "255 0 1"
u的值是255,刚好是uint8的最大值;u+1:255+1=256,但uint8只能存储8位二进制数,256的二进制是100000000,截断后只保留低8位00000000,也就是0;u*u:255*255=65025,计算这个数模256(因为uint8的模是2^8=256),65025 ÷256=253余1,所以低8位是1,输出结果为1。
2. int8的运算分析
再看int8的例子:
var i int8 = 127 fmt.Println(i, i+1, i*i) // "127 -128 1"
i的值是127,是int8的最大正数;i+1:127+1=128,转换成8位二进制是10000000,在补码规则下,这个二进制对应的有符号数就是-128(这是int8能表示的最小负数);i*i:127*127=16129,同样取低8位:16129 ÷256=63余1,低8位是00000001,对应int8的正数1,所以输出1。
关键知识点:Go的整数溢出规则
和部分编程语言会把整数溢出视为未定义行为不同,Go语言对固定大小整数的溢出有明确定义:运算结果会按照模2^N进行环绕(N是整数类型的位数)。无符号整数直接按模运算得到结果,有符号整数则因为补码的特性,会呈现出负数的环绕结果。
内容的提问来源于stack exchange,提问作者Krishnadas PC
相关产品推荐
相关产品推荐

