Computer Systems: A Programmer's Perspective --- 读书笔记2

仲法
2023-12-01

最后一次更新日期:2016-03-10

这本书的中文名字叫《深入理解计算机系统》。当我看到这本书第二章的浮点数部分时,回头发现前面的内容已经不怎么记得了。因此我打算通过写读书笔记的方式来强化自己的理解。笔记中的插图大都来自英文第二版。

第二章 信息的表示和处理

  • 计算机系统都会有一个统一的虚拟地址空间(virtual address space),计算机程序所能访问的地址不能超过这个虚拟地址空间的上限。

以前重装系统时总是说如果超过4G内存的话要装64位的系统,因为32位的系统不能识别超过4G的内存。当时也就当做经验记下了,也是不明白怎么就不能识别了呢,大家都是系统,凭什么我32位的就不行?后来才知道这个4GB的限制是由于32位机子的中虚拟地址空间的上限就是2^32字节=4GB的字节地址空间了,而64位的则能支持2^64=好多好多G的地址空间(据说实际上由于某些原因并不会有那么大,不深究了)。另外还有段时间网传有补丁能够让32位的机子识别4G以上的内存,好奇的我也真的尝试过,并且系统属性里面确实显示了4GB的内存,这。。。想想如果不是补丁作者通过某种方式欺骗我的话那么应该是通过某种机制实现了内存的映射从而变向扩展了系统的虚拟地址空间吧。

  • 一直为记忆十六进制中A-F和对应的十进制数10-15之间的对应关系而苦恼(每次都得掰着手指头A10,B11这样遍历到我要的那个数),书中给出的建议是记忆A(10)、C(12)、F(15)(我改成了记忆E(14),这样要记住的就都是偶数了,并且还是个等差数列),剩余的B、D、F就靠相邻前面的字母+1就行了,试了下效果比之前在脑子里遍历的效果要好。当然主要还是脑子不好使。

  • 如果要保证写出来的程序的移植性的话,在使用数据类型时要注意不用使用对类型敏感的用法。比如我想用int类型的数来存放一个指针,这在32位的机子上没问题(存放指针的字节数量和32机子上int的占用的字节数量一致),但如果我想在64位机子上跑刚刚那个程序的话就可能出问题了(因为64位机子上地址int是32位的,而指针占用64位)

  • 曾经也为记忆端模式而苦恼过,就是记不住小端模式和大端模式,后来明白了:

    • 变量的地址是指变量占用内存块的最小地址
    • 上条所说最小地址存放的是变量的高字节的话,就是大端模式,如果是低字节的话就是小端模式
/** 顺便给一个书中后面习题中提到的判断机器端模式的函数
    小端模式返回1,大端模式返回0
    是不是比较优雅! */
int little_endian(void)
{
    int data = 0x01;
    return *((unsigned char *)&data);
}
  • 在编程中经常会用到一些掩码操作,比如想清除一个long型变量v的低八位为零(比如0xABABABAB低八位清零后是0xABABAB00),我之前的写法是
/** 这段代码存在可移植性的问题! */
x = x & 0xFFFFFF00;

这段代码在大部分32位的机子上是没问题的,但到64位机子上就会出现问题,因为64位机子上long型变量一般占8个字节,上面的掩码0xFFFFFF00会把变量的高32位也清零。因此考虑移植性的写法应该如下:

x = x & ~0xFF;
  • x > yx - y > 0在计算机中的结果并不总是一样。比如xy都是unsigned型的时候,x - y的结果同样是unsigned型的,即面的表达式为在x != y时为永真的。这给我的启示是数据类型的转换和计算的溢出是在计算机内执行计算时必须要考虑的一个问题。

  • 书中有个比较有意思的网络旁注,讲的是C语言中int型数据的最小整数的表示方法:

#define INT_MAX 2147483647
#define INT_MIN (-INT_MAX - 1)

如果直接写成#define INT_MIN -2147483648的话,在引用的时候这个宏的实际值可能会变成2147483648。具体的解释书中给出的网络旁注中讲的很详细。

  • 第二章的后面部分讲到了浮点数,里面讲到的IEEE标准下的浮点数表示法在使用中要注意的一些事项,比如单精度型和双精度型浮点数在位表示下具体的划分,类型转换时的变化,运算时的特性等。这些知识可能对编译器开发者来说更重要一点,对像我这样的应用型程序员了解一下底层的原理也好,万一哪天就遇到个这类的bug也不会一下子蒙逼。
 类似资料: