读CSAPP之字节序列、数和转换

今年是离开校园的第五年,这五年来我一直在从事应用软件的设计、开发工作,大部分时间是在与高级编程语言、设计模式、业务逻辑打交道。它们大多流于表面,久而久之,与技术底层疏远了,诸如计算机组成原理、汇编语言、编译原理、数据结构以及算法慢慢得生疏,时至今日,向上碰到天花板,向下触到花岗岩。五年是一个契机,趁着下一个五年开始之际,我计划用三个月至半年时想间,重新学习这些知识,以期达到巩固基础,厚积薄发的目的。

本篇是我阅读《Computer System: A Programmer’s Perspective》一书的笔记,该书和与之搭配的《Professional Assembly Language》是我当下阅读计划的一部分。

关于字节序列

计算机系统的一个基本概念就是,从机器的角度来看,程序仅仅只是字节序列,机器没有关于初始源程序的任何信息。

在几乎所有的机器上,多字节对象都被存储为连续的字节序列,对象的地址为所使用字节中最小的字节。但是多个字节如何排布则有两种不同的方式。最低有效字节在最前面的方式,叫做小端法。最高有效字节在最前面的方式,叫做大端法。

绝大多数时候,字节顺序不关紧要,但是有三种情形必须考虑,首先,在不同类型的机器之间通过网络传送二进制数据;其次,反编译代码,阅读表示整数数据的字节序列;还有,在C语言中使用强制类型转换。

在使用ASCII码作为字符码的任何系统上都将得到相同的结果,与字节顺序和字大小规则无关,因此,文本数据比二进制数据具有更强的平台独立性。

关于整数 VS. 浮点数

计算机运算中,整数运算满足人们所熟知的真正的数学运算定律,例如乘法的交换律和结合律。但是,浮点数运算,由于表示的精度有限,浮点运算是不可结合的。

整数的表示只能编码一个相对较小的数值范围,但是这种表示是精确的;浮点数的表示可以编码较大的数值范围,但这种表示是近似的。

C语言标准定义了每种数据类型必须能够表示的最小的取值范围,特别注意,它要求正数和负数的取值范围是对称的。但是,C语言并没有规定使用补码来表示有符号整数。

关于类型转换

类型转换分为三种情形,两个位数相同的类型之间转换,高位数的类型向低位数的类型转换,低位数的类型向高位数的类型转换。

对大多数C语言的实现而言,处理同样字长的有符号数和无符号数之间相互转换的一般规则是:数值可能会改变,但是位模式不变。换言之,强制类型转换的结果保持位值不变,只是改变了解释这些位的方式。

当执行一个运算时,如果它的一个运算数是有符号的而另一个是无符号的,那么C语言会隐式地将有符号参数强制转换为无符号数,并假设这两个数都是非负的。对于像<和>这样的关系运算符来说,它会导致非直观的结果。

当低位数的类型向高位数的类型转换时,将一个无符号数转换为一个更大的数据类型时,只需要简单地在表示的开头添加0,这种运算称为零扩展。将一个补码数字转换位一个更大的数据类型可以自行符号扩展,规则是在表示中添加最高有效位的值的副本。

把short转换成unsigned,则先改变大小,然后完成从有符号到无符号的转换。

将一个w位的数截断为一个k位数字时,则丢弃高w-k位。

从float或者double转换成int,值将会向零舍入。

Leave a comment

Your comment