2.1 信息存储
字节:最小的可寻址的内存单位。机器级程序将内存视为一个非常大的字节数组,称为虚拟内存。内存的每个字节都由一个唯一的数字来标识,为它的地址,所有的可能地址的集合称为虚拟地址空间。
2.1.1 十六进制表示法
2.1.2 字数据大小
字长为w位的机器而言,虚拟地址的范围为0-2w-1,程序最多访问2w个字节。
为了避免由于依赖“典型”大小和不同编译器设置带来的奇怪行为,C99引入了int32_t和int64_t,其数据大小固定,分别为4和8个字节。
2.1.3 寻址和字节顺序
小端法:内存中按照从最低有效字节到最高有效字节的顺序存储对象。
大端法:内存中按照从最高有效字节到最低有效字节的顺序存储对象。
2.1.4 表示字符串
C语言字符串被编码为以null(其值为0)字符结尾的字符数组。在使用ASCII码作为字符码的任何系统上都得到相同的结果,与字节顺序和字大小规则无关。因此,文本数据比二进制数据具有更强的平台独立性。
2.1.5 表示代码
二进制代码是不兼容的,它很少能在不同机器和操作系统组合之间移植。
2.1.6 布尔代数简介
布尔环
2.1.7 C语言中的位级运算
2.1.8 C语言中的逻辑运算
2.1.9 C语言中的移位运算
左移:x<<k 丢弃最高的k位,并在右端补k个0。
逻辑右移:x>>k 左端补k个0
算术右移:左端补k个最高有效位 用于有符号整数数据的运算
C语言标准并无明确定义有符号数应该使用哪种类型的右移,实际上所有的编译器/机器组合都对有符号整数使用算术右移,另外,无符号数,必须逻辑右移。C中应保持位移量k<位数w。
java中,x>>k 算术右移,x>>>k 逻辑右移,实际位移量k mod w
2.2 整数表示
2.2.1 整数数据类型
2.2.2 无符号数的编码
w位无符号数:0-2w-1 ,无符号数编码具有唯一性
2.2.3 补码编码
最高位xw-1称为符号位,权重 -2w-1,1为负,0为非负。
表示范围:最小值符号位为1,剩下为0,为 -2w-1,最大值符号位为0,其余为1,为2w-1-1。补码同样有唯一性。
- 补码范围不对称,最小负数没有与之对应的整数。一半符号位为1的数表示负数,一半符号位为0的数表示非负数,0是非负数,所以能表示的数比负数少一个。
- 最大的无符号数值刚好比补码的最大值的两倍大一点。
- 最大的无符号数值和补码的-1都是全是1的串。
反码:最高有效位的权是 -(2w-1-1) 故负数时比补码大1
原码:最高有效位是符号位,用来确定剩下的位应该取负权还是正权,浮点数中使用
这两种表示方法,0都有正0和负0之分
2.2.4 有符号数和无符号数之间的转换
补码转化为无符号数:
无符号数转化为补码:
2.2.5 C语言中的有符号数和无符号数
C语言标准:没有指定有符号数要采用某种表示,但是几乎所有的机器都使用补码。大多数数字都默认是有符号的。无符号必须加后缀u或U。
java:明确补码,单字节称为byte,而不是char。这些具体的要求是为了保证无论在什么机器运行,java程序都能表现的完全一样。
2.2.6 扩展一个数字的位表示
较小数据类型转换为较大数据类型是可行的
无符号数零扩展:开头添0
补码数的符号扩展:添加最高有效位的值
2.2.7 截断数字
截断到k位,原位数w位
2.2.8 关于有符号数和无符号数的建议
程序员往往忽略隐式强制类型转换
安全漏洞:
避免方法:不使用无符号数,如Java。
2.3 整数运算
2.3.1 无符号加法
模数加法形成了一种数学结构,阿贝尔群。它是可交换的和可结合的。它有一个单元0,并且每个元素有一个加法逆元。
2.3.2 补码加法
2.3.3 补码的非
无符号非:
它们的位模式是相同的
补码非的位级表示
-
各位取反 末位加1
-
从右边开始的数直到第一个1不变,剩下第一个1左边的位的取反
2.3.4 无符号乘法
2.3.5 补码乘法
XDR库的安全漏洞
2.3.6 乘以常数
大多数机器上,整数乘法指令相当慢,需要10个或者更多时钟周期,然后其它整数运算(加法 减法 位级运算 和 移位)只需要1个时钟周期,故编译器使用移位和加法的组合代替乘以常因子的乘法。
2.3.7 除以2的幂
整数除法总是舍入到0,向下舍入一个正值,向上舍入一个负值,3.14舍入到3,-3.14舍入到-3
无符号数:逻辑右移
补码:算术右移,会导致向下舍入,而不是向0舍入,出现了偏差
修正:加偏置量
与乘法不同,除以2的幂可以通过逻辑右移或者算术右移实现,但不能推广到任意常数
2.3.8 关于整数的最后思考
整数运算实际上是一种模运算。补码提供了既能表示正数也能表示负数,同时使用了与执行无符号算术相同的位级实现。
无符号数据类型虽然简单,但是会出现一些我们意想不到的行为。我们还看到这种数据类型会以出乎意料的方式出现,如书写整数常数和调用库函数。
2.4 浮点数
2.4.1 二进制小数
2.4.2 IEEE浮点表示
情况1:规格化值
情况2:非规格化的值
情况3:特殊值
2.4.3 数字示例
假定6位格式,k = 3 的阶码位和n = 2的尾数位,偏置量23-1-1=3
可以观察到可表示的数并不是均匀分布的——越靠近原点越密集
假定8位格式,k = 4 的阶码位和n = 3的尾数位,偏置量24-1-1=7
2.4.4 舍入
四种舍入方法:
向偶数舍入:也称为向最接近的值舍入,是默认的方法,如果是中间的数,则向下或者向上舍入,使得结果的最低有效数字是偶数。
优点:避免了统计学上的偏差,因为它50%的时间向上舍入,50%的时间向下舍入。