C语言中的整数溢出
对于初学者来说,C语言的整数溢出可能一开始可能会不好理解。对于一个字节的 unsignde char类型和signed char 类型。赋值一个超出其存储范围的数值时,
其真实存储的数值并不等于我们赋值的数据。要弄清整数溢出问题,首先必须清晰计算机中数值都是以补码形式存储的,要会原码、反码和补码的转换。
下面分有符整数溢出和无符整数溢出分析。
一、有符整型溢出
比如下面这个程序,输出不是129而是-127。
我们知道对于有符整型(signed char)它的存储范围为[-128,127],129已经超出向上溢出了。129的机器码为【1000 0001】,计算机会取这八位作为补码存储。
补码【1000 0001】是个负数,求其原码减少1再对数值位取反可得到其原码为【1111 1111】,这个值就是-127(最高位为符号位1,代表负数)。也可以把[-128,127]
看作汽车里程表,当向上超出时就重新从起点开始。129-127 = 2,从新从-128开始这个值就是-(128-2+1) = -127。
再举一个列子,下面这个程序输出的结果为-112而不是400,同样的分析可得出结果。
400的机器码为【0000 0001 1001 0000】(2^8+2^7+2^4),计算机会取出低八位【1001 0000】作为补码进行存储,作为补码这明显是个负数,我们减1再对数值位取反可以得到其原码
为【1111 0000】,这个数是-112(2^6+2^5+2^4)。用循环思想也可以验证, 400超出上限400-127 -256 = 17,所以为-【128-17+1】 = -112。一般我们在将int型数据赋给char型变量的时候
编译器也会发出警告如下:warning: overflow in conversion from 'int' to 'signed char' changes value from '400' to '-112' [-Woverflow]|。
二、无符整型溢出
无符整型溢出就简单多了,因为正数的补码和原码一致。道理也是一样的,这里举一个简单例子分析一下。下面的程序输出结果不是288,而是32。
我们知道unsigned char一个字节存储值的范围是[0,255],288明显已经向上溢出了。288的机器码为【0000 0001 0010 0000】(2^8+2^5),计算机取出低八位【0010 0000】作为补码
,正数补码就是原码,这个数就是32,循环思想也可验证。同样的编译器也会发出相关警告:warning: unsigned conversion from 'int' to 'unsigned char' changes value from '288' to '32' [-Woverflow]|
整型溢出问题,只要对于计算机数值存储形式(补码)和补码原码转换有了解就不难理解了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)