第二章 信息的表示和处理
信息存储
十六进制
特点:每个数字占4位
十六进制转二进制:直接将每个数字的二进制依次排列即可
二进制转十六进制:则从后往前每四位分一部分最前面不足补0
字节顺序
小端法和大端法:大端法是正序,从最低有效字节到最高有效字节,小端法相反。大多机器使用小端法
0x1234567的大端序和小端序
字符串
特点:以null
(值为0
)结尾,数字x
的ASCII
码为0x3x
,不受大端小端的影响在任何系统结果相同
位移运算
左移:末尾补k
个0
,取后m
位
逻辑右移:前补k
个0
,取前m
位(无符号数)
算数右移:前补k
个首位的数,取前m
位(常用)
特殊情况:k > m
,则位移 k mod m
位
整数表示
有符号数与无符号数的数值范围
符号 | 数值 |
---|---|
UMaxw | 2^w - 1 |
UMinw | 0 |
TMaxw | 2^(w-1) - 1 |
TMinw | -2^(w - 1) |
C
#define INT_MAX 2147483647
#define INT_MIN (-INT_MAX - 1)
不对称性:|TMinw| = |TMaxw| + 1 UMaxw = 2TMaxw +
,因此不是所有负数都存在相反数
补码two’s complement
特点:将最高有效位解释为负权,也称符号位,权重为-2^w-1
(其二进制共w位),正数补码为原码,负数补码为其二进制取反后加一
转换为无符号数的规则:位值不变,只是改变了最高位的解释位的方式,即是否为符号位
转换计算方法:-1 和UMaxw
位表示相同,全1的串,0 ~ TMaxw
之内转换数值不变,范围之外转换加上或减去2^w
隐式类型转换:
-
相互赋值
-
printf
输出时使用不对应的格式化字符串 -
算术运算或比较一边存在无符号数则另外一边强制转为无符号数
扩展和截断
无符号数转换为一个更大的数据类型:零扩展,即二进制前导补0
补码转换为一个更大的数据类型:符号扩展,即二进制前导补符号扩展位的值
长度不同的类型之间的转换:长度转一致之后再类型转换,如short
转unsigned
要先转为int
再转unsigned
截断规则:舍弃高位,补码将最高位转换为符号位
关于符号数与无符号数的建议
尽量避免无符号/有符号类型的混用,因为这样可能会进行隐式类型转换,造成非预期的错误
C
#define KSIZE 1024
char kbuf[KSIZE];
void *memcpy(void *dest, void*src, size_t n);
int copy_from_kernel(void* user_dest, int maxlen)
{
int len = KSIZE < maxlen ? KSIZE : maxlen;
memcpy(user_dest, kbuf, len);
return len;
}
例中,memcpy
函数的定义中n
类型为size_t
,若len
输入负数则会导致n
为一个很大的数,使程序读取到它没有被被授权的内核内存区域
IEEE浮点表示
公式: V = (-1)^s * M * 2^E
位名称 | 释义和值 |
---|---|
s | 符号位,一个单独的位编码符号位 |
M | 尾数,一个二进制小数,编码为n位小数字段frac |
E | 阶码,用于对浮点加权,编码为k为的阶码字段exp,被解释为以偏置形式表示的有符号整数 |
f | frac / 2 ^ n |
Bias | 偏置值,2^(k-1) - 1 |
类别 | 特点 | E | M |
---|---|---|---|
规格化的值 | 阶码域有0有1 | e - Bias | 1 + f |
非规格化的值 | 阶码域全为0 | 1 - Bias | f |
特殊值 | 阶码域全为1,s = 0为正无穷,s=1为负无穷,能够表示溢出的结果,小数域非0称为NaN | \ | \ |
标准浮点格式
单精度浮点数值分类
8位浮点格式的非负值示例
注意:浮点数可以表示的值范围比整数大但只是近似表示,数字越大精度越低,其运算不具有结合性,且单精度与双精度值进行比较可能会发生错误,当超过最大的规格化的值时会发生溢出