视频教程:b站九曲阑干【合集】CSAPP
信息的存储(上)
- 程序将内存看作一个非常大的数组(虚拟地址空间),每个元素存的是地址。
- 地址的长度字长目前是32位到64位。
- 1bit = 8位二进制数 = 1个字节。
- 字节的存储顺序:大端法(IBM,Sun)正序,小端法(intel,android,ios)逆序,新机器(ARM)支持双端配置
- 32位程序可以允许在32位机器或者64位机器上,但是64位程序只能允许在64位机器上。
- 32位机器虚拟地址空间4GB,64位机器虚拟地址空间16EB。
- 一个字节=8位二进制数,这种一位一位表示数据的方法称为位模式。
- 十进制虽然好理解,但是不好转换,二进制好转换,但是太冗长,因此一般位模式的表示一般采用十六进制。
- 十六进制的字母不区分大小写。
- 二进制转十六进制时,如果位数不满足4的倍数,则左边补0。
- 二进制与十六进制的快速转换:
假设将2的n次方转换为十六进制,n=i+4j,则十六进制的表示为2的i次方后面接j个0- 例:2的11次方转换为十六进制,11=3+4*2,则十六进制表示为2的3次方后面接2个0,即为0x800
- 十进制转n进制:用十进制数除n,取余,用商继续除,直到商为0。
- n进制赚十进制:类比二进制转十进制乘幂即可。
信息的存储(下)
- c语言中每个字符串都有一个结尾字符null,用ascii码表示,ascii码具有较好的平台移植性。
- 移位的规则:
- 左移,低位补0
- 逻辑右移,高位补0
- 算数右移,原最高位是1就补1,是0就补0
- 虽无明确规定,但对无符号数,c语言中采用逻辑右移,对有符号数,采用算数右移。
- 补码用来表示有符号数,符号位不只是负号,是有数值含义的
- 0101中符号位的0=0,所以0101=5
- 1011中符号位的1=-8,所以1011=-5
- 对无符号数来说,最大值就是所有位=1时表示的值,最小值就是0;
对有符号数来说,最大值就是符号位为0,其余位为1时表示的值,最小值就是符号位为1,其余位为0时表示的值
所以,有符号数所有位=1时表示-1,注意和无符号数的最大值区分开 - 有符号数和无符号数的转换:位模式不变,强行改变解释,因此数值会发生变化。
- 当执行运算时同时出现有符号数和无符号数,此时有符号数会被强制转换为无符号数进行运算,会出现-1>0的情况。
- 强制转换时如果是大数向小数转换,会出现大数可能被截断的情况。
整数的运算(上)
- 无符号数加法可能会遇到溢出:
~例如1个字节的255+1=0,0是如何得到的?低位全0进位,最高位1溢出丢失。溢出不会报错,可以通过对和进行判断是否大于其中一个无符号值来判断是否出现溢出的状态。
~有符号加法会出现正向溢出和负向溢出,溢出结果推算同上,注意有符号数的位模式即可。如果正+正为负,负+负为非负,即可发现出现了溢出。 - 怎么求-x?
无符号数:0的逆元是自己,其他逆元=最大值-自己
有符号数:最小值的逆元是自己,其他逆元=-自己
整数的运算(下)
- 乘法和除法可以等价为移位和加减法的组合,注意有符号数的右移是算数右移。
- 整数除法有余数时,采取向0舍入的规则,此时有符号数的负数需要先加上偏置再进行算术右移,右移k位,则偏置=2的k次方-1。
- 与乘法不同,整数的除法右移规则只能针对2的幂次,不能推广至任意常数,对一般常数的除法暂缺
浮点数(上)
-
float由一个符号位+8个阶码位+23个小数位表示
-
根据阶码位的三种状态,可表示四种数值:
- 阶码不全为0或全为1,表示规格化值
- 阶码全为0,表示非规格化值
- 阶码全为1,小数为0,表示无穷值inf
- 阶码全为1,小数为不为0,表示非数值nan
-
规格化值的计算公式如图,注意偏置的计算与阶码位数相关
-
非规格化的数用来表示正负0,以及非常接近0的小数,计算公式如下图所示
-
特殊值的计算公式如下图所示
浮点数(下)
- 可以用浮点数来表示整数,通过上述公式推理浮点数的符号位、阶码和小数位。
- 浮点数有四种舍入方式:
- 向偶数舍入 可避免向同一方向导致的统计误差
- 向0舍入
- 向下舍入
- 向上舍入
- 由于舍入导致的精度损失,浮点数的加法和乘法都不满足结合率和分配率。
- int、float、double三种数值转换时,要考虑溢出和精度损失导致的结果异常。