CSAPP Chapter 2 - 信息的表示和处理 阅读笔记
1 信息的表示和处理
信息 = 二进制位的组合 + 对位组合的解释:无符号,补码,有符号整数,浮点数。
介绍了一点 C 语言的演变历史:汇编不方便 —> ANSI C -> ISC C90 -> ISO C99 -> ISO C11(可以在编译时通过
-std=cxx
指定编译所使用的版本)
1 个字节 = 8 位 -> 内存中信息的编码以字节为单位 -> 机器级程序将内存看作一个大的数组(虚拟内存)-> 利用指针来存储地址 -> 指针是机器级代码的概念,其组成包含类型+值,但是类型在内存当中是不可见的,在内存中所有东西都是没有感情的字节数组。-> 指针的大小 = 字长(总线一次传输数据的最大字节数)-> 虚拟地址空间以字编码 -> 字长:虚拟地址空间的最大大小 -> 32 位机器:4GB 64 位机器:16EB -> 32位程序
& 64位程序
指的是:如何编译
字节的表示方法包括:16 进制,10 进制,2 进制等等。
字节序:对跨越多个字节的程序对象,我们必须明确:
- 地址在哪里:存储的最低字节处
- 如何排列他们:大端法 or 小端法?
ASCII 编码与 Unicode 编码。Unicode 和 UTF-8 是什么关系?
布尔代数与位运算,其有分配律,且(a^b)^a = b
,位向量掩码,经典的inplace_swap
利用异或进行值交换
逻辑运算,short circuits
移位运算:
- 逻辑右移
- 算术右移(有符号数算术右移,无符号数逻辑右移,Java 使用
>>>
来进行逻辑右移)
注意:
- 移动 k 位(k 很大时),移动 k % w 位
- 加法和减法的优先级 > 移位运算优先级,如
1<<2+3<<4
,因此移位时记得加括号
2 整数的表示和运算

通过引用
#include <stdint.h>
,然后使用INTX_t
,就可以使用特定位数的某种类型。可以使用宏%" PRId32 "
来打印串。在
<limits.h>
中限定了INT_MAX
,INT_MIN
,UINT_MAX
等等
INT_MIN = -(-INT_MAX - 1)
3 浮点数的表示
浮点数针对范围大,精度低的表示。整数针对范围小,精度高的表示。
- 单精度浮点数(
float
):1 位符号位 + 8 位阶码 + 23 位位数 - 双精度浮点数(
double
):1 位符号位 + 11 位阶码 + 52 位尾数
其表示包含四种情况:
阶码部分是使用了移码计算,其计算方法如下:
$$ bias = 2^{k-1} - 1 $$
$$ exp = E - bias $$
规格化数:阶码部分不全为 0 也不全为 1 其尾数计算方法如下:
$$ M = 1 + f $$
非规格化数:阶码部分全为 0 其尾数部分为$f$,阶码部分计算如下:
$$ exp = 1 - bias $$
这种阶码的计算方式实现了非规格化数到规格化数的平滑过渡。
无穷大:阶码部分全为 1,尾数部分全为 0
NaN:阶码部分全为 1,尾数部分不为 0
4 重点习题
- 2 进制,16 进制,10 进制之间的转化
- 大端法和小端法对同一个数值的不同存储方式
- 整数和浮点数表示的重合部分
- 布尔代数和位运算
- 位向量掩码
- 布尔运算之间的组合(or,and,xor,not)
- 逻辑运算
- 使用位级运算和逻辑运算实现
^
- 移位运算的计算
- 同样位表示的无符号和补码值
- 相同位表示下,无符号数和补码值的转换
- 无符号数和有符号数的比较(默认转化为无符号数后比较)
- 有符号数/无符号数的符号扩展
- 不同类型+大小之间的值的转换
- 数值的截断
- 隐式转换可能带来的程序问题,以及如何避免
- 无符号数的加法和溢出判定
- 无符号数求反
- 有符号的加法和溢出判定
- 有符号数求反
- 无符号的乘法
- 补码乘法
- 无符号的乘法
- 乘以 2 的幂
- 乘以常数 & 2 种移位运算
- 无符号数除法
- 有符号数除法(向上舍入)
- 小数的二进制表示和十进制表示
- 浮点数的表示(规格化,非规格化,INF,NaN 的情况)
- 浮点数的计算
- 浮点数的范围
- 整数和浮点数之间的转换,以及其共有部分
- 浮点数的舍入
- 不同类型之间转换带来的精度损失(溢出或舍入)