目录
整型在内存中的存储-原反补
- 计算机中的整数有三种2进制表示方法 即原码 反码和补码
- 三种表示方法均有符号位和数值位两部分 符号位都是用0表示“正” 用1表示“负”
- 正数/无符号数的原、反、补码都相同
- 负整数的三种表示方法各不相同:
原码: 直接将数值按照正负数的形式翻译成二进制就可以得到原码
反码: 将原码的符号位不变 其他位依次按位取反就可以得到反码
补码: 反码+1就得到补码- 对整数来说 正数负数(只要是整数) 内存里存的都是补码
对整数来说 内存里存的都是补码
在计算机系统中 数值一律用补码来表示和存储 原因在于:
1.补码与原码相互转换 其运算过程是相同的 不需要额外的硬件电路
2.使用补码 可以将符号位和数值域统一处理 同时加法和减法也可以统一处理(CPU只有加法器)
如下图 计算1-1的时候 其实就是1+(-1) 因为CPU只有加法器
如果用原码直接算 结果-2显然错误
用补码计算就对了 1的原反补都一样 -1算出补码是1111…1111
补码相加的结果给int 最高位那个1被截断了
计算结果就是:000000…00 这个结果也是补码 发现补码最高位是0 则正数 则原反补相同 结果就是0
在刚刚的计算过程中发现 就是直接把补码加起来 并没有区分符号位或者数值位 直接算出结果的补码
3.补码避免了0和-0的问题 下图以char为例
4.存的是补码 计算机在计算的时候 用的也是补码
既然存储的是补码 那么在下面讨论char的范围的时候 也就是讨论八个比特位的空间能存多少个数值 也就是八个比特位能表示多少个补码 这些补码对应的数值就是取值范围
无符号unsigned char:[0,255]
无符号 都是有效位 都是正数 原反补相同 直接把排列组合成的二进制读出来 就是范围
100000000-1=11111111
100000000-1=2^8-1=256-1=255=11111111
有符号signed char:[-128,127]
8个bit位 排列组合成补码 放在内存 有256种可能 下图是依次+1
注意1000 0000这个特殊的补码
对于signed char而言 127+3就是补码往下移三个位置对应的值 127+1 = -128 127+2 = -127 127+3 = -126
同理可得short(16位)是-32768~32767
一些其他的理解/记忆的方法
1.看成一个轮回


2.补码的权值
问题:仍然以signed char 也就是8个bit为为例 直接告诉你八位的补码 能否不转换成原码而直接算出它对应的数值?
同理
如果补码是1111 1110 则直接算出-128+64+32+16+8+4+2+0=-2
如果补码是1000 0001 则直接算出-128+0+1=-127
再看一个例子 如果补码是1111 1111 数值是?
3.补码本质是取模的结果
这里mod256是因为都是以char为例 也就是8bit为 也就是2^8
如果是short 那就是mod2^16了
其实对于signed char a来说
a=128 和 a=-128
a=255 和 a=-1
他们在内存中发生的事情是一模一样的
4.从负数到正数 和 正数到负数的两种视角
以前面的3.为例 仍然以char为例
-1在内存里存的补码其实是1111 1111(即255的原码)
-2在内存里存的补码其实是1111 1110(即254的原码)
-128在内存里存的补码其实是1000 0000(即128的原码)
所以如果告知char里存的是负数m 就可以通过m+28=k知道其对应的正数
这个正数k的原码其实就是负数m的补码
如果是short 那就是m+216=k int那就是232
再从正数到负数 把255存进signed char[-128,127] 那肯定是溢出了 实际上得到什么?
这个时候1.那个圆圈就可以派上用场 比如说把255给signed char
想象那个圈上一共是有28=256个排列组合 255相当于转一圈再往后退一个 那就是-1
再比如256 相当于正好转了一圈 那就是0
以此类推 下图a=a+b之后 显然是溢出了 那a实际上是多少?
已知INTMAX=231-1 则a+b=231-1-1+231-1-2=232-5
对于signed int来说 那个圈圈就是有232个排列组合 232-5相当于转了一圈再退五个 也就是-5
同理如果把234-6赋值给int 也就是转了三圈再退六个 那得到的就是-6
总结
对于有符号的而言 他们的最小值的补码都是100…00(全为0的情况 假设共有n个0)
有一个很好的记忆方法记住最小值 那就是-2n
比如short就是-215 int就是-231
最大值就是2n-1 比如char就是27-1 int就是231-1
对于无符号而言 就看多少个比特位 比如char就是8个比特位 那么取值范围就是[0,28-1] 这个-1其实就是把28个排列组合里的0给减掉
既然这样 那么如果是-21亿左右 那大概率是用signed int这一类的数据类型保存的属性值
而且这个-21亿大概率就是最小值了
根据前面的说法 数值应该是-231
找了个视频 发现确实如此
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/qq_57030936/article/details/158617828























