CSAPP第二章知识点归纳(信息的表示和处理)
基本概念 信息存储
字节顺序(大端法和小端法)表示字符串布尔代数 整数表示
无符号数加法无符号数求反补码加法补码的非无符号乘法补码乘法除以二的幂的补码除法,向下舍入偏置 浮点数(重点)
IEEE浮点表示浮点数的舍入
CSAPP第二章知识点归纳(信息的表示和处理)基本概念
无符号编码基于传统的二进制表示法,表示大于零或者等于零的数字补码(two’s-complement)编码是表示有符号整数的最常见方式(正负数)浮点数编码是表示实数的科学计数法的以2为基数的版本(近似表示,不是精确的)结果太大不能表示就会发生溢出 信息存储
内存的每个字节都由一个唯一的数字来标识,称为它的地址,所有可能的地址的集合就称为虚拟地址空间在C语言中,十六进制数以 0x 或 0X 开头进制转换的方法(虽然简单,但有可能忘记,还是摘抄下来!)
对于一个w位的机器而言,虚拟地址的范围是 0~ 2 w − 1 2^w-1 2w−1 ,程序最多访问 2 w 2^w 2w字节下图为32位和64位计算机数据类型的典型的大小
字节顺序(大端法和小端法)最低有效字节在最前面的方式称为小端法,最高有效字节在最前面的方式叫大端法
(需要注意的是上图中,是字节的顺序的不同,在单个字节的八个比特中是按顺序的)(简单记忆:按正常顺序,容易读的是大端法)(大端小端指的是单个数据对象的存储方式,而不是其他的所有字节序列,只有数据是有这两种区分的)
打印程序对象的字节表示的代码
#include表示字符串typedef unsigned char *byte_pointer; void show_bytes(byte_pointer start, size_t len) { size_t i; for (i = 0; i < len; i++) printf(" %.2x", start[i]); //line:data:show_bytes_printf printf("n"); } void show_int(int x) { show_bytes((byte_pointer) &x, sizeof(int)); //line:data:show_bytes_amp1 } void show_float(float x) { show_bytes((byte_pointer) &x, sizeof(float)); //line:data:show_bytes_amp2 } void show_pointer(void *x) { show_bytes((byte_pointer) &x, sizeof(void *)); //line:data:show_bytes_amp3 } void test_show_bytes(int val) { int ival = val; float fval = (float) ival; int *pval = &ival; show_int(ival); show_float(fval); show_pointer(pval); }
C语言中字符串被编码为一个以null(值为0)字符结尾的字符数组(一般使用的是ASCII标准)Unicode标准的相关知识重点:
使用32位表示字符,占用4个字节替代编码,常见的只用1个到2个字节,不常用的要多一些的字节UTF-8表示将每个字符编码为1个字节序列,使得ASCII中的和UTF-8中表示一样 布尔代数
C中的位级运算
C中的逻辑运算(与位级运算区别,逻辑运算认为所有非零的参数都是True,而参数0表示False,返回0和1)
整数表示下面这张表还是看看,说不定考试直接用了不知道是什么
补码编码
补码编码将字的最高有效位解释为负权(下面的Tmin和Tmax为能表示的最大和最小的数)
B
2
T
w
(
x
⃗
)
≐
−
x
w
−
1
2
w
−
1
+
∑
i
=
0
w
−
2
x
i
2
i
T
M
i
n
w
≐
−
2
w
−
1
T
M
a
x
w
≐
∑
i
=
0
w
−
2
2
i
=
2
w
−
1
−
1
∣
T
M
i
n
w
∣
=
∣
T
M
a
x
w
∣
+
1
B2T_w(vec{x})doteq-x_{w-1}2^{w-1}+sum_{i=0}^{w-2}x_i2^i\ TMin_wdoteq-2^{w-1}\ TMax_wdoteqsum_{i=0}^{w-2}2^i=2^{w-1}-1\ |TMin_w|=|TMax_w|+1
B2Tw(x
)≐−xw−12w−1+i=0∑w−2xi2iTMinw≐−2w−1TMaxw≐i=0∑w−22i=2w−1−1∣TMinw∣=∣TMaxw∣+1
例子:
有符号数的另外两种标准(不重要,了解)
有符号数和无符号数之间的转换
强制类型转换保持位值不变,只是改变了解释这些位的方式
补码转换为无符号数(相互之间的转换)
T
2
U
w
(
x
)
=
{
x
+
2
w
x
<
0
x
x
⩾
0
U
2
T
w
(
x
)
=
{
u
u
⩽
T
M
a
x
w
u
−
2
w
u
>
T
M
a
x
w
T2U_w(x)=begin{cases} x+2^w&x<0\ x&xgeqslant0 end{cases}\ U2T_w(x)=begin{cases} u&uleqslant TMax_w\ u-2^w&u>TMax_w end{cases}
T2Uw(x)={x+2wxx<0x⩾0U2Tw(x)={uu−2wu⩽TMaxwu>TMaxw
相互之间的转换图解:
C语言在执行一个运算数是有符号而另一个是无符号的时候,会隐式地将有符号参数强制类型转换为无符号数(C语言默认创建有符号数,无符号数要在末尾加u) 符号扩展
B
2
T
w
+
k
(
[
x
w
−
1
,
.
.
.
,
x
w
−
1
⏟
k
次
,
x
w
−
1
,
x
w
−
2
,
.
.
.
,
x
0
]
)
=
B
2
T
w
(
[
x
w
−
1
,
x
w
−
2
,
.
.
.
,
x
0
,
]
)
B2T_{w+k}([underbrace{x_{w-1},...,x_{w-1}}_{k次},x_{w-1},x_{w-2},...,x_0])=B2T_w([x_{w-1},x_{w-2},...,x_{0},])
B2Tw+k([k次
xw−1,...,xw−1,xw−1,xw−2,...,x0])=B2Tw([xw−1,xw−2,...,x0,])
就是说比如111表示的是-1,那么符号扩展了以后,11111也是表示-1,将符号位(最高位扩展) 截断数字
无符号数的截断就是直接将高位的除去,相当于mod 2的k次方补码的截断和无符号数的一样,把它当作无符号数,也就是直接截断高位,然后在按补码的规则计算值
整数运算 无符号数加法
相关的图片解释
相当于是加起来等于0(忽略进位) 补码加法
先把它当作无符号数进行运算,然后在转换成补码
补码的非
无符号和补码的乘法结果在截断后是相同的(比如上面三位的例子),原本是不同的,原理书上P67,不用看
整数乘法比移位和加法的代价大很多,很多C编译器使用以移位、加法和减法的组合来消除整数乘以常数的情况
除以二的幂的补码除法,向下舍入非负的数与无符号数除以二的逻辑右移效果是相同的,向下舍入到最接近的整数,但对于负数来说,除法会产生向下舍入,而不是正确的向零舍入
偏置
为了使负数补码除以二是向零舍入的,需要在移位的时候添加 偏置 来修正原来不合适的舍入
C变量x和k分别有补码值x和无符号数值k,且0$ leqslant
k
k
k <
w
,
则
当
执
行
算
术
移
位
时
,
C
表
达
式
w,则当执行算术移位时,C表达式
w,则当执行算术移位时,C表达式 (x+(1<
浮点数(重点) IEEE浮点表示
标准表示方法
V
=
(
−
1
)
s
×
M
×
2
E
V=(-1)^stimes Mtimes 2^E
V=(−1)s×M×2E
其中 s 表示符号,负数为1,正数为0
M 是尾数
E 是阶码
标准浮点格式
三种情况
浮点数的例子(容易忘记偏置,特别是非规格化的是1-bias,尾数前面隐含有一个1(规格化))
浮点数的舍入
四种舍入方式的比较
其中向偶数舍入在中间的值的时候是向最靠近的偶数进行舍入,其他的情况下按最接近的数字进行舍入向偶数舍入举个例子,如10.110舍入到 1 2 frac{1}{2} 21,因为要舍入的末尾为1000正好为中间,所以向偶数舍入就是舍入后末尾为0,所以结果为11.0
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)