0%

CSAPP读书笔记-02

CSAPP读书笔记-02

浮点数陷阱

在第二章最初,给出了“浮点运算是不可结合的”这样一个结论,乍一看有点令人费解,但仔细看了看例子,发现其实结合浮点数在内存中的存储方式反而很容易理解,不过就是这种表达很容易让人误会,颇不可取。

实际上由于浮点数在内存中存储时,计算机存储的是它的尾数,因此在一个数的基础上,给它加上或者减去太小的浮点值,都会导致最终产生截断,表现出来就是“什么也没有发生”的效果。

书中提到的:

1
(3.14 + 1e20)-1e20

正是这样一个例子。

其中的1e20远大于3.14,于是实际发生的事情就是(3.14+1e20)所得的结果为1e20,再减去1e20,于是就得到了看起来很不合理的0。因此在使用浮点数的时候一定要注意精度的问题。

如果一定要在跨度很大的范围内进行浮点数运算,最好将同一优先级下,数值范围相近的操作数先运算。

“虚拟内存”的抽象

大多数计算机的最小可寻址内存单位就是“字节”。

机器级程序将内存视为一个非常大的字节数组,称为虚拟内存

这里又复习了一下第一章提到的“抽象”概念,所谓“虚拟内存”,就是对主存和I/O设备的抽象。并且这段话还具体讲了一下“虚拟内存” 抽象的方式,使得这个抽象概念更加明晰。

每台计算机都有一个字长(word size),指明指针数据的标称大小。

这里的“字长”可以比较“字节”的概念。“字长”并不等于“字节”,一个“字”可能包含多个字节,并且是取决于机器的位数的。

所谓“指针数据的标称大小”,我的理解就是在这台机器上存储某个虚拟内存地址的指针变量的位数。更进一步说,应该就是PC寄存器(程序计数器)的大小,因此PC寄存器的大小(也就是“字长”)限制了计算机的最大寻址范围,超出“字长”所能表示的最大值的虚拟内存地址对计算机来说是没有意义的。

并且还要注意的是,编译结果的二进制程序是32位还是64位并不取决于机器,而是取决于具体使用的编译器和编译方式。

大端法和小端法

之前忘记在哪儿看到过关于大端法和小端法的描述,但因为毕竟不是CS专业,了解了一下也没有记住,今天看书的时候倒是认真推敲了一下,发现了一些有趣的东西,也对这两种存储顺序有了更深的理解和记忆。

最低有效位在最前面的(存储)方式,称为小端法(little endian)

最高有效位在最前面的(存储)方式,称为大端法(big endian)

其实按人类的正常思维和书写习惯,很显然大端法是一种更加自然的方式,但却很少被采用,连两种主流的移动端操作系统都没落着;而小端法则是一种更加符合逻辑的存储顺序,可能也更加适合在计算机当中表达。

说是这么说,但实际上转念一想,为什么大端法存储顺序就更贴近人的思维了呢?其实就连在书面上表达的时候,将内存单元按地址增大的顺序从左往右排列也不过是人为规定的而已;对计算机来说,地址的高位、低位并不存在左右之别,反而将低字节放在低地址更便于机器操作。