0%

CSAPP 学习笔记 1 信息的表示和处理

前言

上一周看完了第一章,这一周继续看第二章。本章的内容和信息的表示和处理有关,这部分内容之前修计算机组成原理时有学习到,所以阅读起来比较顺利,预计下周能顺利读完此章。

正文

这一章的内容分为四小节,分别是:

  • 信息存储
  • 整数表示
  • 整数运算
  • 浮点数

信息存储

上篇笔记谈到了信息,什么是信息?信息是数据+上下文。

在不同的上下文中,数据会有不同的含义。一个字节,既可表示一个字符,也可表示范围在[0, 256)的无符号整数,也可表示范围在[-128, 128)的有符号整数,还可以表示具有8个元素的集合,等等。

大多数机器使用8位的块,称为字节,作为最小的可寻址的内存单位,而不是直接访问内存中单独的位。字长为32位的机器,寻址的最大空间是$2^{32}$字节,而字长为64位的机器,寻址的最大空间就是$2^{64}$字节。什么是字长呢,字长用于指明指针数据的标称大小。

因为一个字节有8个位,用二进制表示起来有点冗长,而用十进制表示法的话,与位模式的互相转化会很麻烦。于是就有了十六进制数来表示位模式,在二进制和十进制取了折中,既方便表示,又不那么难读。

假如我们想要访问跨越多字节的对象,需要建立两个规则:这个对象的地址是什么,以及在内存中如何排列这些字节。对象地址的寻址范围根据字长而定,当字长为$w$时,可寻址空间为$2^{w}$。确定好对象的起始地址,还需要知道它有多少个字节以及如何排列这些字节。假设读取对象为int,有四个字节,且在内存中从低址到高址的内容为0x00000001,采用大端法读取就是$1$,采用小端法读取就是$2^{24}$。大端表示法比较符合人类的习惯,而小端法需要将数据按字节倒序排列。这些数据在机器中的字节排列通常对我们没有影响,但当涉及到网络编程时,就需要关注网络传输数据和机器存储数据的区别了。

整数表示

整数在计算机中有多种表示形式,比如原码、补码、反码等。

而编程语言中遇到的整数类型,比如short, int, long long等,是对整数大小的限制。

而常说的有符号数、无符号数,则是在人类限制整数能否表示负数而产生。我认为有符号数和无符号数的设计其实意义不大,只用一种有符号数来表示整数就足够了。有了无符号数和有符号数,就需要用户去关注无符号数和有符号数的转化,一些隐式转化很容易引起出人意料的隐蔽错误。在Java中,并没有无符号数的概念,而在C语言中,有符号数和无符号数的转化,其实整数在底层的位表示中是不变的,只是C语言在不同的上下文中对它进行了不同的解释。

无符号数,采用简单的原码编码即可。而有符号数,一般采用补码编码,因为相对于源码、反码,它能表示更多一个数,更重要的是,机器中的位表示与整数是一个双射关系,很优雅。

无符号数和有符号数的转化,在理解了机器的位表示始终不变以及补码的相关知识后,我们可以总结出规律。我们这里假设两者的位数都为$w$。将无符号数转化为有符号数,当超过其表示范围时,需要减去$2^w$。将有符号数转化为无符号数时,负数需要加上$2^w$。

(全文完)