CSAPP:第2章 信息的表示和处理
- 第二章勉勉强强读完了,第一遍读,有部分地方不太理解或者理解不透彻的,望指出
2.1 信息存储
2.1.1 十六进制表示法
- 主要讲了进制转换,如二进制如何转16
2.1.2 字数据大小
- 字长点概念——指明指针数据的标称大小(nominal size)
- 两种伪指令的特性与兼容性问题——一般是64兼容32,如下所示:
- linux>gcc -m32 prog.c
- linux>gcc -m64 prog.c
2.1.3 寻址和字节顺序
- 1、大、小端法
- 大端=顺序存
- 小端=以字节为单位反着存
- 有一个比较有意思的点:
- 芯片可以兼容大小端,但是特定的OS只支持一种——Android和IOS只支持小端
- 需要考虑字节顺序的三种情况
- 1、网络传输时(系统间传输可能存在大小端不同的问题,故需要协议作为中介)
- 2、阅读表示整数数据时
- 3、编写规避正常类型系统的程序时
2.1.4 表示字符串
- 用char数组(ascii码)+最后一个终止字节(0x00)
2.1.5 表示代码
- 由于不同机器类型使用互不兼容的指令和编码方式,即使是完全一样的进程,运行在不同操作系统上也会有不同的编码规则——二进制代码时不兼容的,因此很少有二进制代码在不同及其系统组合之间移植,如:win与linux
2.1.6 布尔代数简介
- 四种布尔运算:~ & | ^
- 分别表示:取反、AND、OR、异或
2.1.7 C语言中的位级运算
- 同上四种
2.1.8 C语言中的逻辑运算
- 分别为:&& || !
- 常见的,需要注意的是逻辑运算的结果只能是0、1,即TURE、FALSE
2.1.9 C语言中的移位运算
- <<为左移, >>为右移
- C中并没有明确规定右移的类型(逻辑还是算数),该问题可能导致可移植性问题——不同系统的定义不同
- Java中 >> 表示算数右移,>>>表示逻辑右移
- C语言中 加减法的优先级比移位高
2.2 整数表示
- 符号含义,本小节我读的很痛苦,究其本质就是忘看这段符号,导致很多简单公式愣了好一会
2.2.1 整型数据类型
- 分为有符号和无符号两种,其中C、C++默认有符号,但支持无符号,Java只支持有符号
2.2.2 无符号数的编码
- B2Uw=Bin are to Unsigned
- 这个公式就是位数*权重,且最高位不是符号
- 书中还提到一个概念,双射,即y=f(x),xy一一对应,不存在一对多、多对一的情况
2.2.3 补码编码
-
B2Tw=Binary to Two’s-complement
-
Two’s-complement=补码
-
该公式与无符号的区别是最高位的权重是-1而不是1,这是由补码的特性决定的(1=负),补码也是双射
-
但是 反码和原码不是双射——0的两种表示方法(±0)
2.2.4 有符号数和无符号数之间的转换
- C语言中的强制类型转换只是改变了解释这些位的方式,而不改变位置上的值,尤其是对最高位来说。
- 转换公式
- 就我自己来说,我一般是化为二进制再转。而书中的公式是:
- 补码转无符号
- 无符号转补码
2.2.5 C语言中的有符号数与无符号数
- int和unsigned
2.2.6 拓展一个数字的位表示
- 无符号数=0扩展(补0即可)
- 补码数=最高位扩展(补最高位的值)
- 有意思的是书上还给了证明,我的理解就是对于负数的补码,把权重带进去就可以证明是正确,对于正数就是0扩展
- 有意思的是书上还给了证明,我的理解就是对于负数的补码,把权重带进去就可以证明是正确,对于正数就是0扩展
2.2.7 截断数据
- 无符号数的截断就是留下低位即可
- 补码的截断类似无符号数,但是取低位的最高位作为符号为
2.2.8 关于有符号数与无符号数的建议
- 转换要指明,隐式转换,最为致命。
2.3 整数运算
2.3.1 无符号数加法
- 它实际上是这样的一个梯形上升,而不是平滑曲面,因此需要稍微考虑正溢出的问题。
- 相关公式是:
2.3.2 补码加法
- 补码由于有正、负,因此需要考虑正、负溢出。下图为补码溢出情况,个人觉得有必要了解下(大致范围)
- 下面T2U的公式转换参见上面补码表示的公式
2.3.3 补码的非
- ~ 每位都取反 如:1000 --> 0111 === -8 -->7
- 因此可以得倒一个有趣的东西:-x = ~x+1
- 其公式如下:
2.3.4 无符号乘法
- 下面公式中mod作用是取低位
2.3.5 补码乘法
- 公式如下:
- 补码乘法有一个特性,即无符号数与补码乘法的位级等价性,说人话就是:低位相同
- 推到过程是,我个人还是不太喜欢这种纯理论,书下方有几道联系,做完你会发现确实如此:
2.3.6 乘以2的幂
- 乘以2的幂=右移位,高位丢弃
- 关于补码乘以2的幂,需要考虑一出的问题(正变负这种)
2.3.7 除以2的幂
- 相当于左移
2.4 浮点数
2.4.1 二进制小数
- 尾数与阶数,讲了一般意义上的小数的表示
2.4.2 IEEE浮点表示
- 这里介绍了两种,分别是(符号位、阶码位数、尾数位数),其中,尾数一般有一个隐藏的1
- float:1,8,23
- double:1,11,52
- 这里的浮点数一般有三种情况
- 1、规格化的浮点数
- 阶码E = e - Bias (对于Bias有 float=127 ,double是1023)
- 2、非规格化的值
- 对于这里我有点不理解,为什么会平滑转换,我翻了很多网上童鞋的笔记,发现没有指出的,希望有缘人能解个惑~
- 目前的知道的是他把尾数隐藏的1用来给E+1了
- 当表示非常接近0.0的数的时候,非规格化值会表现出一个特性——逐渐下溢(精度丢失?)
- 3、特殊值
- 当阶码全1的时候出现
- 当尾数全0 === ∞
- 当尾数非0 === NAN(not a number)
- 比如根号-1的结果就是NAN,或者∞-∞也是
- 当阶码全1的时候出现
- 1、规格化的浮点数
2.4.3 数字示例
- 下图可以表示出越接近0,数越密集,则可以越平滑地过渡到0
- 下图印证了2.4.2的说法
2.4.4 舍入
- 有以下四种常用舍入方式
- 其中,像偶数舍入有点像我们常说的四舍五入。
2.4.5 浮点运算(留坑)
- 关于这里我有点不明白阿贝尔群,这个概念我到现在还没懂(毕竟是菜鸡),流坑
- 常见流程无非就是:对阶-尾数运算-舍入-规格化,还有个溢出判定
- 浮点加法不具有结合性,满足单调性
2.4.6 C语言中的浮点数
- 有float和double,对于特殊值有专门定义,如INFINITY(∞),NaN(NAN)
2.5 小结
- 重复以上。