深入理解计算机系统 第二章
原码,反码,补码:
原码:二进制本身,正数第一位为0,负数第一位为1。
反码:正数的反码是它本身,负数的反码是原码的基础上,符号位(第一位)不变,其它位取反。
补码:正数是它本身
负数是反码的基础上+1
C的整数更精确但范围不大,浮点数范围大但不精确因为是近似值
一个字节由8位(比特)组成
C语言中:
char为1字节
Int为4字节
Long在32位程序中为4字节,在64位程序中为8字节
float为4字节
double为8字节
确定大小的整数类型(更利于准确控制数据表示):
Int32_t:4字节
int64_t:8字节
多字节对象被存储为连续的字节序列,对象的地址为所使用字节中最小的地址
例如:int x的地址为0x100 那么它会被存储在内存为 0x100,0x101,0x102,0x103中(因为int为4字节)。
如上:我可以将int或者是任何其它变量看成一段字节序列,就像一段连续数组一样,当我们进行位运算操作的时候,就是在操作整个类似于连续数组的字节序列。
大小端法:
强制转换数据类型:
其实本质上是在计算机读取到要转换的数据类型时,将指针指向要转换的数据类型的指针,而不是改变原来的数据类型指针。
计算机的一个基本概念:
从机器的角度来看,程序仅仅只是字节序列(多字节对象int等),机器没有关于原始源程序的任何信息,除了可能有些用来帮助调试的辅助表以外。
int的范围:-1e32~1e32-1
就是符号位被用来做了个补充,用来代表多出来的那个负数!
有符号数和无符号数之间的转换:
位:二进制中此时的1或0
值:此时为w位的话 那么值就是2的w次方*(1或者0)
有符号数-1和无符号数2的32次方的位表示是完全一样的 因为-1的二进制是1*10的32次方 而2的32次方的二进制也是1*10的32次方。并且两者相加为2的w次方
无符号常量通常有后缀字符: ‘ U ’ or ‘ u ’
B2Uw是无符号位编码。(u是无符号数 这里可以记成 二进制数转无符号数)
B2Tw是补码编码(t是补码 这里可以记成 二进制转补码)
U2Bw 和T2Bw:
1.U2Bw 无符号数 转 二进制
2.T2Bw 补码 转 二进制
T2Uw:
并且:
扩展一个数字的位表示:
一种常见的运算是在不同字长的整数之间转换,例如,从一个较小的数据类型转换到一个较大的数据类型。
将一个无符号数转换为一个更大的数据类型,只需要简单地在表示的开头添加 0,这种运算称为零扩展。
有符号数就在符号位前面补1或0(正数0,负数1)其BU2w一样,这就是符号扩展。
截断数字:
将较大的数据类型转换到较小的数据类型
整数运算:
C语言执行一个有符号数而另一个是无符号数的时候,会隐式地将有符号参数强制转换成无符号数,并假设两个数都是非负的。
无符号加法:
溢出的结果减去2的w次方
判断无符号加法是否溢出:
sum=x+y
当sum<x or sum<y
则溢出 因为减去了2的w次方
判断补码加法是否溢出:
同符号相加 结果不为同符号
因为相加时 要截断w位 来避免数据大小的不断扩张 所以
正溢出的结果要减去2的w次方
负 加上
补码的非:
将补码全部去取反的结果 + 1
如:0101 — 1011
无符号乘法:
补码乘法:
先计算 然后 模2的w次方,再把无符号数转换为补码
乘以常数
在计算机中 整数的乘法指令相当慢 需要10或更多的时钟周期 而移位和加法却只用一个时钟周期 所以计算机用移位和加法来代替乘法
移位可以获得2的次幂的数 我们可以将要乘数x转换成2的次幂的加法
除以常数
除法比乘法更长时钟周期(30)所以除法用移位来计算
引入符号:
整数除法总是舍入到零(正数往小取。负数往大取)
无符号除法
无符号整数都是非负的,所以,无符号整数的右移,和整数除法的结果是一致的,即舍入到零。
补码除法
偏置:
浮点小数:
比如二进制小数 10.111 = 1*2的一次方 + 0*2的零次方 + 1*2的负一次方 + 1*2的负二次方 + 1*2的负三次方
EEE754 标准中规定 float 单精度浮点数在机器中表示用 1 位表示数字的符号(S),用 8 位表示指数(E),用 23 位表示尾数(M),即小数部分。对于 double 双精度浮点数,用 1 位表示符号,用 11 位表示指数,52 位表示尾数,其中指数域称为阶码。IEEE754 浮点数的格式如下图所示。
注意,IEE754 规定浮点数阶码 E 采用"指数e的移码-1"来表示,请记住这一点。为什么指数移码要减去 1,这是 IEEE754 对阶码的特殊要求,以满足特殊情况,比如对正无穷的表示。
移码(又叫增码)是对真值补码的符号位取反,一般用作浮点数的阶码,引入的目的是便于浮点数运算时的对阶操作。