最后一次更新日期:2016-03-10
这本书的中文名字叫《深入理解计算机系统》。当我看到这本书第二章的浮点数部分时,回头发现前面的内容已经不怎么记得了。因此我打算通过写读书笔记的方式来强化自己的理解。笔记中的插图大都来自英文第二版。
以前重装系统时总是说如果超过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 > y
和x - y > 0
在计算机中的结果并不总是一样。比如x
和y
都是unsigned
型的时候,x - y
的结果同样是unsigned
型的,即面的表达式为在x != y
时为永真的。这给我的启示是数据类型的转换和计算的溢出是在计算机内执行计算时必须要考虑的一个问题。
书中有个比较有意思的网络旁注,讲的是C语言中int
型数据的最小整数的表示方法:
#define INT_MAX 2147483647
#define INT_MIN (-INT_MAX - 1)
如果直接写成#define INT_MIN -2147483648
的话,在引用的时候这个宏的实际值可能会变成2147483648
。具体的解释书中给出的网络旁注中讲的很详细。