一,int类型在内存是如何存储的?
数据类型 占用字节数 取值范围
int 4byte -2^31 ~ 2^31-1
unsigned int 4byte 0 ~2^32
1,占用的比特位数
int占用4个字节,每个字节有8个比特位,所以有32个 0-1 的二进制位数。注意:int类型有正负号,unsigned int 没有正负,所以int要用一位来标识正负
2,符号的表示方法
int类型占用的比特位中,左起第一个位(最高位)就是符号位。0表示正数,1表示负数。其余后面31是数值位。
3,数字0怎么表示?
3.1,因为有了正负数,那么就会有 +0 和 -0 。(注意:0有了两种表示:+0,-0)
+0的表示方法:0000 0000 0000 0000 0000 0000
-0的表示方法:-2^31
0就用 +0 的表示方法
3.2,正数部分 2^31-1 ,之所以要减一,就是因为数字0占用了 +0 。负数不需要表示0,-0 就用来表示 -2^31
3.3,int类型的数字 -1 ,在内存中32个比特位上该如何表示?
10000000 00000000 00000001 左边第一个1表示负号,后面31位表示数值部分“1”。---->然而,并不是这样的
二,补码
计算机中的符号数有三种表示方法:原码,反码,补码。这三种表示方法都有符号位和数值位两部分,符号位用 0 表示正,用1 表示负,但是数值的表示,这三个就不相同了。
1,原码
原码是计算机中一种对数字的二进制定点表示方法。原码表示法 最高位位是符号位,正数最高位是0,负数最高位是1。
如何用原码表示一个数?
-1的表示:10000000 00000000 00000001
+1的表示:00000000 00000000 00000001
为什么不用原码在内存中表示数值呢?
举个栗子:用8位二进制表示 1 和 -1,然后让这两个数做加法运算
十进制 原码
1 0000 0001
-1 1000 0001
结果(原码) 1000 0010
结果(十进制) -2
这运算结果显然不对。计算机在计算时,加法计算的算法更加便捷,减法会先转为负数,再进行加法运算。所以,原码的符号位不能直接参与运算
总结:原码是有符号数的最简单的编码方式,便于输入输出,但是作为代码加减运算时比较复杂。所以计算机不采用这种编码方式存储符号数。
2,反码
规定:正数的反码和原码相同,负数的反码是对其原码逐位取反,但是符号位除外。
正数 和 +0 ,他们的反码就是原码本身。对于8位二进制的 +1,原码,反码都是 0000 0001
负数 和 -0,符号位不变,其余位数逐位取反(1换成0,0换成1),对于8位二进制的-1,原码:1000 0001,反码:11111 1110
我们再来做一次运算:1+(-1)= 0
十进制 原码 反码
1 0000 0001 0000 0001
-1 1000 0001 1111 1110
结果(反码) 1111 1111
结果(原码) 1000 0000
结果(十进制) -0
计算结果是-0,而我们加法运算的结果是0。
问题:由于-0的存在,使得二进制和十进制的互换不是一一对应的关系。这样就需要计算机增加额外的物理硬件配合运算,所以已经抛弃了用反码存储数据
3,补码
3.1,补码就是基于反码的 -0 问题而出现的。补码的计算方法:
正数和 +0 的补码是原码
负数先计算反码,然后反码加1,得到补码
3.2,补码如何换算成原码呢?
如果是正数或 +0 的补码,那么原码就是补码。
如果是负数或-0的的补码,那么先将补码减掉1,得到反码,再将反码取反,得到原码
我们还是以:1+(-1)= 0 为例
十进制 原码 反码 补码
1 0000 0001 0000 0001 0000 0001
-1 1000 0001 1111 1110 1111 1111
结果(补码) 0000 0000
结果(反码) 0000 0000
结果(原码) 0000 0000
结果(十进制) +0
计算结果正确,+0就是数字0的唯一表示
注意:8位二进制补码1000 0000没有对应的反码和原码。
所以,int类型在内存中,以补码的形式存储。
三,运算
1,按位与(&)
参加运算的两个数,换算为二进制(0,1),进行与运算:只有当相应位上的数都是1时,才取1,否则该位为0
将10和-10进行按位与(&)运算(需要转成补码后再进行计算):
10 0000 0000 0000 1010
-10 1111 1111 1111 0110 (-10的原码:1000 0000 0000 1010 ,-10的反码:1111 1111 1111 0101 ,-10的补码:1111 1111 1111 0110)
- - - - - - - - - - - - - - - - - - -
按位与结果: 0000 0000 0000 0010
2,按位或(|)
参加运算的两个数,换算位二进制(0,1)后,进行或运算。只要相应位上存在1,那么该位就取1,都不为1,就为0.
将10和-10进行按位与(|)运算(需要转成补码后再进行计算):
10 0000 0000 0000 1010
-10 1111 1111 1111 0110 (-10的原码:1000 0000 0000 1010 ,-10的反码:1111 1111 1111 0101 ,-10的补码:1111 1111 1111 0110)
- - - - - - - - - - - - - - - - - - -
按位或结果: 1111 1111 1111 1110
3,按位异或(^)
参加运算的两个数,换算位二进制(0,1)后,进行异或运算。只要相应位上的数字不相同时,才取1,若相同,就取0
4,取反(~)
参加运算的两个数,换算为二进制(0,1)后,进行取反运算。每个位上都取相反值,1变成0,0变成1。
对10进行取反(~)运算:
0000 0000 0000 1010
---------------------
1111 1111 1111 0101
5,左移(<<)
参加运算的两个数,换算为二进制(0,1)后,进行左移运算,用来将一个数的每个二进制位全部向左移动若干位。
对10左移2位( 就相当于在右边加2个0 ):
0000 0000 0000 1010 (10)
--------------------
0000 0000 0010 1000 (40 = 10 * 2^2)
6,右移(>>)
参加运算的两个数,换算为二进制(0、1)后,进行右移运算,用来将一个数各二进制位全部向右移动若干位。
对10右移2位(就相当于在左边加2个0):
0000 0000 0000 1010
--------------------
0000 0000 0000 0010
来源:https://www.cnblogs.com/inspred/p/10987936.html