CSAPP第二章(上)

十六进制表示法

用十进制表示二进制比较麻烦,所以人们通常用十六进制来表示二进制

可以记住ACF三个十六进制数字对应的二进制数字的数值来推算BDE

A: 0X1010
C: 0X1100
F: 0X1111

2^n和十六进制的转换

2^n == 1后面n个零
n = i + 4j
转换为十六进制就是0X(2^i)(j个零)

比如对于2^11
i = 3
j = 2
转换为十六进制就是0X800

十进制数转换为十六进制数字

辗转相除法

实质就是0X?????是十进制数转换成的十六进制数字,每次对16取余,得到的就是右移一位被抛弃的数字,最后合起来就是原数

十六进制数转换为十进制数字(无符号数)

从低位向高位依次乘以20到2n-1(n为位数)

十六进制数转换为十进制数字(有符号数)

计算机中对于有符号数字的编码采用补码的形式

最高位代表负权重

从低位向次高位依次乘以20到2n-2,最高位乘以2^n-1

64位字长和32位字长

字长:总线一次传输可以传输的位数。
字长指明了指针数据的标准大小。

大多数64位机器都可以运行32位的程序,这是一种向后兼容。

对于32位的程序和64位的程序主要的区别是程序是如何编译的

gcc -m32 -o hello32 hello.c
gcc -m64 -o hello64 hello.c

大端法和小端法

intel小端,IBM和SUN为大端(大多数)新的处理器很多支持双端法

大端:低位地址存放权值大的数字
小端:低位地址存放权值小的数字

代码区分在p67

左移和右移

左移:往左移动一位,最右面补0
逻辑右移:往右移动一位,最左边补0(无符号数)
算数右移:往右移动一位,如果最高位是1,就在最高位补1(有符号数)

数的存储方式

无符号数和有符号数

有符号数最高位表示负权重

无符号数的最大值:2^(n)-1

有符号数的最小值:-2^(n-1)

1000 0.....
有符号数的最大值:2^(n-1) -1
0111 1.....

无符号数和有符号数之间的转换

无符号数和有符号数位模式没有改变但是解释这些数的方式改变了。

有符号数转为无符号数:

  • 当最高位为0时,直接转换
  • 当最高位为1时,

无符号数转换为有符号数

  • 当最高数值为0时候,直接转换
  • 当最高数值为1时候,该数减去2^n就是转换过去的数值

有符号数和无符号数计算时,有符号数会隐式转换为无符号数来进行计算

无符号小变量转换为无符号大变量

在拓展的位直接补充零

有符号小变量转换为有符号大变量

符号位为0,直接补0
符号位为1,直接补1

不管多少位,全为1都表示-1,所以负数前面补充1不会改变大小

有符号小变量转换为有符号大变量

直接截断,然后变为想要的位数。

这种转换会改变原有数值

数的运算

溢出

unsigned char a = 1;
unsigned char b = 255;
unsigned char c = a+b;

a+b超过了uchar的最大值,发生了溢出
此时c = 0;

无符号数的加法

0000 0001 + 1111 1111 = 1 0000 0000 = 0000 0000;

此时超过了uchar的界限,要把最前面的1消去,相当于减去2^n

当发生溢出后,无符号数相加的结果小于其中任何一个数。

有符号数的加法

正溢出:要减去2^n
0111 1111 + 0000 0001 = 1000 0000;
负溢出:要加上2^n
1111 1111 + 1000 0001 = 1 0111 1111 = 0111 1111;

当两个正数相加得到的结果为负数,或者当两个负数相加得到的结果为整数就发生了溢出

加法逆元

两个数相加为0(相反数?)

无符号数的加法逆元:两个数相加为2^n

1-1 = 1+254

有符号数的加法逆元:
-2^n<= x <= 2^n-1

  1. 当该数不是最小数值,直接符号位取反
  2. 当该数是最小数值的时候,加法逆元就是本身

乘法

任何一个二进制数乘以2^n就是让这个二进制数左移n位然后补充0

二进制数乘一个普通的数转换成二进制数乘以2^n之间进行的加法

除法

对于无符号数除以一个2^n就是逻辑右移
对于有符号数除以一个2^n就是算数右移

posted @ 2021-04-12 16:45  陌天森  阅读(144)  评论(0)    收藏  举报