通俗简析Int类型的范围和溢出

本文详细解析了int类型的取值范围,介绍如何通过原码、反码和补码表示负数,以及在数值运算中如何避免溢出,特别是当正数接近最大值时的边界情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通俗易懂的Integer类型的范围和溢出简析

1) int类型的取值范围

前置知识:

两位比特有几种组合形式?

00

01

10

11

四种。

它可以表示几个数?分别为几个?

4个,是0,1,2,3。

好,

众所周知,int类型是4个字节的变量类型,由于1个字节表示8个比特(bits),所以用二进制类型表示的一个int应该为:

00000000 00000000 00000000 00000000

一共32个比特.。

所以说,理论上,一共有(2的32次方)种组合形式。如果每种格式在逻辑上表示为1个不同的数,那么一个int可以表示(2的32次方)个数。

但实际上,常识上的int是包含正数和负数的,于是为了表示方便(反正2的32次已经很大了),将int类型从左往右数第一个0作为符号位,不作为值的计算范围,且规定一个int变量这一个位上,为0为正,为1为负。所以能够表示值的位数只有31位了。例子如下:

0 |0000000 00000000 00000000 00000111 说明它为正数

1 |0000000 00000000 00000000 00000111 说明它为负数

现在问题在于,有一个数它既不是正也不属于负,它是谁? 他是0。

那么0该怎么表示?它的首位为1还是0?

为了方便,我们就规定他为 00000000 00000000 00000000 00000000,更符合人的直觉。可是10000000 00000000 00000000 00000000该表示什么?听我慢慢道来。

我们常常在书上可以看到,int类型的取值范围是 -2的31次方~2的31次方减1

2的31次方减1我们很容易理解,因为它等于

01111111 11111111 11111111 11111111

但我们想要表示另一个极端情况,-2的31次方我们会用什么表示?

没错,就是 10000000 00000000 00000000 00000000,就是那种我们感觉也可以当0取的可能性,它有了新的职责,它用来表示一个独特的值。

好,这样我们就要进入到比较难的环节了,负数到底怎么表示?

这里要说到原码 反码 补码的概念。

原码是方便人去理解的,计算机运算和编程不会去用原码。

原码符合人的直觉认知,判断流程就是:

看第一位是0还是1决定它是不是负数 + 看后面二进制数值位的值决定它到底是几。

如:

0 |0000000 00000000 00000000 00000111 说明它为正7

1 |0000000 00000000 00000000 00000111 说明它为负7

但计算机中,数值的表示与存储用的是补码

大白话就是,程序中的int中的数值用的是补码,计算机不在乎什么原码

个人认为,反码补码就是为了方便计算机进行对负数的处理在研究出来的,可以更方便的表示负数的值,以及进行正负数的计算。

反码是:

负数的反码是在其原码的基础上,符号位不变,其余各个位取反。
正数的反码和原码是一样的!规定就是这样的。

[+1] =

[00000000 00000000 00000000 00000001]原=

[00000000 00000000 00000000 00000001]反

[-1] = [10000000 00000000 00000000 0000001]原
= [11111111 11111111 11111111 11111110]反

负数的补码即在其反码的基础上+1,
正数的补码等于原码

[-1] =

[10000000 00000000 00000000 00000001]原=

[11111111 11111111 11111111 11111110]反=

[11111111 11111111 11111111 11111111]补,

负数在计算机中的表示是用补码来表示的。

注意!正数的三个码都一样,所以正数就是特例情况我感觉三个码压根不是给正数用的,计算机去理解正数非常的方便。

但负数就不一样了。所以要引入其他码。

PS:个人理解,数值位更倾向于表示相对的大小,配合符号位才能更好的展现一个int的值到底是多少。我感觉补码这个名字不太好,弄的它好像是配角一样,其实感觉补码才是三种码中最重要的。

你去用C语言编译器输出-1的值二进制就是11111111 11111111 11111111 11111111

肯定有人会想,为什么-1在计算机中的表示会那么麻烦?直接用

1 |0000000 00000000 00000000 00000001不好吗?

真的不好,请想想到底是-1更大还是-999999更大?是-1更大吧!由于数学逻辑上,负数的特殊性导致其绝对值越大,负数反而小,不然正负数计算会变成一团乱麻。为了能够更正确的理解,负1在计算机中表示为,即补码为

1 |1111111 11111111 11111111 11111111 其实-1才是负整数中最大的数哦!

1 |1111111 11111111 11111111 11111110 这是-2!

1 |0000000 00000000 00000000 00000001 这是-2的31次方减1!

依次类推,补码表示为10000000 00000000 00000000 00000000 的它作为-2的31次方,它才是负数里最小的数。它非常非常特别,感觉就是个特例,最高位既代表符号又代表数值,也就是说-2的31次方的原码和补码是相同的。

2) int的溢出

有下面一个int型变量,

01111111 11111111 11111111 11111111

没错,他是int里最大的正数,也是最脆弱的正数,它现在在溢出的边缘上

如果我们动一动它,加个1会怎么样(计算机:行吧)

符号位:?什么B动静? woc!

10000000 00000000 00000000 00000000 <–2的31次方 (这里是补码)

没错,你给一个正数加一,它突然就变成了负数。因为你动用了符号位,把符号位参与到了数值的变动,导致想要的数据出了问题!他没有变成+2的31次方!

再加个1怎么样?

10000000 00000000 00000000 00000001 <–2的31次方-1 (这里是补码,别老惦记那原码了) (其实它在变大了,毕竟加一了)

所以在面对数值变动,溢出一定要考虑,不然从负数突然到正数出的bug绝对够你喝一壶的。

第一次写博客,写的很粗糙,只是分享自己在学习中的一些想法,有错误指正和改进欢迎提出!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值