2`底层运算、内存基础
底层运算
底层表示
计算机底层是用二进制(0/1)表示的,每个二进制数字用一个位存储,它是最小到的传输单位bit位/比特,最小的存储单位是byte字节 == 8位(因为一个位通常不能表示一个完整的信息)
一个ACSII码(有128个字符,包括数字,字母,通用/控制符号)占一个字节,它是在构建的汇编阶段的编码方式之一,即将这些字符转换为计算机可以理解的二进制码,比如这样的操作’a’ - ‘a’ 的结果为0
原码,反码,补码
我们现在可以用不同的二进制组合表示不同的字符,那么如何表示 正负,加减运算……呢?
1
2
正数1的原码为: 0 0000001
负数-1的原码为:1 0000001
展开
- 原码
- 二进制的首位当作符号位,[ 0 ]表示正数,[ 1 ]表示负数
1
2
3
4
5
加法运算 :0+1=1,1+0=1,0+0=0,1+1 = 0(进位1)
1010
+ 0010
= 1100
展开
- 加法运算
1
2
3
4
3 + (-5) = -2
0 0000011 原
+ 1 0000101 原
= 1 0001000 原 == -8
展开
- 计算机只会加法不会减法,所以应该将减法换算为加法(例如3 - 5 = 3 + (-5)),但直接用原码计算的结果是错误的
1
2
-5的原码为:1 0000101
-5的反码为:1 1111010
展开
- 反码
- 为了保证结果正确,数学家规定所有参与运算的数均以反码形式存储和计算
- 正数的反码为本身,负数的反码为,除符号位不变其余位取反,
- 运算结果应再次转为原码
- 正数反码与原码相同
- 负数从反码到原码,除符号位不变其余位取反 ```c++ 1 + (-1) = 0 0 0000001 反
- 1 1111110 反 = 1 1111111 反 1 0000000 原 == -0 ```
- 但是它有时仍会出现问题,比如上面的用例,0没有负数
- 补码
- 补码正是用来解决+0和-0的问题,数学家规定所有参与运算的数均以补码形式存储和计算
- 正数的补码为本身,负数的补码为反码再加上1
- 原码到补码:原->反->补
1
1 1111110 -> 1 0000001 -> 1 0000010
展开
- 运算结果应再次转为原码
- 正数补码与原码相同
- 负数补码到原码:除符号位不变其余位取反,再加1
1
2
3
4
5
-1 + (-127) = -128
1 1111111 补
+ 1 0000001 补
= 1 0000000 补
0 0000000 原 = 0//结果错误
展开
- 特殊情况、数据范围:
- 有符号bit位可以表示的范围是:-2^(bit-1) —— 2^(bit-1)-1
- 比如8位1字节,由于首位是符号位,因此只能用剩下的7位表示:
- -2^7 —— 2^7
- 1111 1111 —— 0000 0000 —— 0111 1111
- -127 —— -1 , 0 , 1 —— 127
- 由于1000 0000 == -0 ,0没有负数,我们用它表示-128,128是不可以表示的
- 因此能表示的范围为[ -128, 127 ]
- 无符号数,首位非符号位,因此可以用8位表示
- 还是看8位的情况:
- -2^8 —— 2^8
- 0000 0000 —— 1111 1111
- 0 —— 256
- 无符号数 == 正数,即原反补都相同
- 有符号bit位可以表示的范围是:-2^(bit-1) —— 2^(bit-1)-1
- 特殊情况、数据范围:
1
2
3
4
-1 + (-127) = -128
1 1111111 补
+ 1 0000001 补
= 1 0000000 补 == -128的补码(1000 0000->0111 1111->1000 0000)
展开
- 所以我们再来看刚才的错误结果,对于-128是特殊的,数学家想出了一种统一的新方式去求补码
- 正数的原反补是它自身,负数的原反和上述一样计算,补码为 绝对值 取反加1
- 最后会比较补码,而非转换后原码的结果
- 所以我们再来看刚才的错误结果,对于-128是特殊的,数学家想出了一种统一的新方式去求补码
内存基础
字长 == CPU一次计算能处理的二进制数据的最大位数 存储容量 == 总内存 寻址范围 == 存储单元数量,根据地址总线的位数决定的,2的N次方 按字编址:意味着以字节为单位对存储单元进行编号,也就是每个地址对应一个字节
本文由作者按照 CC BY 4.0 进行授权