第二章---信息的表示与处理
CSAPP第二章
第一章暂时不记录,从第二章开始。
首先这一章讲了整数,无符号,有符号,浮点数,以及他们之间运算时候可能会出现的错误等。比较枯燥吧,看了3遍才有点意
下面记录一下主要的知识点以及理解,推导过程不记录,原书上尽量理解吧(ps;推导过程理解了一半),没必要记住所有东西,只要明白什么时候会出错,怎么解决就行。
2.1:
首先明白,现在大多数计算机 1字节=8位,字节是存储某种数据类型时候的最小单位,比如最小的char类型是1字节。但实际计算机底层存储某种数据类型时候是按位存储的,相当于如果要存储20,内存里面就会以 00101000 来存储。所以如果一个四字节的数,则踏实32位,如果按照2进制进行存储,最大可以表示2^32-1大小的数字(无符号类型)
2.1.1:
十六进制表示法:为了简化2进制表示而产生的,每一位范围是0-F,即0-15,和二进制转化时直接把每一位用4位二进制表示,转换为10进制直接按幂展开。
十六进制之间也可以直接进行四则运算,跟十进制类似,只不过将底数变为16即可,比如加的时候,超过了15才会进位。
2.1.2:
注意64位机器和32位机器里面有的数据类型所占的字节数是不一样的,但是我们可以用类似于int32_t int64_t 这样的数据类型来让他们无论在哪种机器上都是相同的。
2.1.3:
多字节对象存储时有两个问题:
1.这个对象的地址是什么?处理方法是我们只存储第一个字节地址,然后根据该对象的字节数计算出来剩下字节的地址,
2.如何排列这些字节?小端法或者大端法,小端法是以最低有效字节为头进行排列的,大端法与之相反,一般都是小端法。排列的不同会导致输出以及解释时候的顺序不同。
2.1.7-8-9:
C语言之中有一些位级别上面的运算和一些逻辑运算,
位级别上的运算: ~ & | 异或 ,一般是将其他进制的参数转换成2进制,然后进行位级运算,最后再转换回其他进制,因为2进制位级运算简单一些,计算机也只能够识别0,1.
逻辑运算,|| && 等,这个时候运算的基本单元就是一个表达式之类的,而不是对位进行运算,
移位运算:<< >> 左移很简单,右移分为逻辑右移和算术右移,算术右移需要填满最高位,一般用于有符号数,无符号数只能用逻辑右移
注意如果移的位数超过了该数据本身的位数,则移动 (位数%该数据的位数) 位
2.2:整数的表示
整数分为无符号和有符号,区别是后者的最高位表示符号位,明白下面几点;
1.有符号数和无符号数的最大值,最小值是不一样,比如有符号的4位数,最大只能是2^3-1,0111,最小是1000,-2^3,但是无符号数由于只能是正的,所以4位无符号数据就可以是2^4-1最大。
2.他们之间进行转换的时候,会因为最高位的意义不同有很大的区别,注意转换只是说改变解析的方式,而不是改变表示方法。会出现正溢出,负溢出等问题,转换时候有公式,不记录了,理解就行。所以我们有时候需要判断是否会有溢出产生,比如正正相加得到了负,就有了正溢出,负溢出相反。
3.当无符号数和有符号数之间进行比较或者运算时,如果有无符号数,会自动将有符号数转换为无符号数进行解释。
4.符号扩展有两种,
(1):无符号的零扩展,即从低位到高位,将多出来的位全部用0填充
(2):补码扩展,同样从低位到高位,将多出来的位全部用原来的最高位来填充,
一般是在数据类型转换的时候会用到,低字节数据----强制转换为-----高字节数据,
5.截断数字
一般是高位数据强制转换为低位数据时候进行的,比如32位转换为16位,会直接把多出来的位全部丢弃掉
上面这些我们在进行比如隐式类型转换,和显式类型转换时候计算机底层进行的操作,仔细想想很好玩的
2.3:整数运算
明白了怎样表示整数,那么他们运算的时候,到底是怎样运作的呢?
无符号加法:
比如,现在有两个4字节32位无符号int类型的数据,32位无符号int最大能够表示2^32-1,现在如果有两个数相加之和大于最大值,那么就会进行截断,只保留32位,将多余的位截断,这样子的话毫无疑问会计算出来不正确的数值,截断之后的数的值是:原本的数-2^32,因为你是截断了一个33位,33位表示的就是2^32,当然这里是他们之和没有超过2^33的情况,如果之和更大的话会截断更多位。
补码加法,
即有符号的数据类型之间的运算,由于有符号是分正负的,所以这个时候就会有正溢出,负溢出,举个例子,比如一个4位的有符号数据,0111,0101,分别表示7,5,相加是 1100,这时候很明显产生了溢出,4位有符号最大能够表示 7 ,那么在之后解释的时候,还以有符号的方式解释,1100就会解释为
-8+4= - 4,两个整数相加确产生了负数,这就是正溢出以及底层到底是怎么样的,具体转换规则有公式,没必要记。负溢出类似,只是最高位从1变为了0。
所以有时候进行判断的时候我们需要考虑是否会发生溢出的情况,导致得到不正确的结果
同样的,乘法也会有溢出问题,只是范围不同,但是同样的溢出时都会进行截断,截断原理都是相同的,
乘法运算,补码乘上一个常数
大多数机器之中乘法运算会进行的很慢,所以一般都是转换为移位进行计算的,因为移位运算进行的很快,所以可以极大的提高效率。
先看一个简单的例子,11 乘 2^2,11的二进制表示,1011,1011<<2 = 101100 = 44,可以看到,左移两位就是乘2^2,得出规律,一个数乘上2^k,即将他的补码左移k位即可,
除法暂时不记录。
2.4浮点数
。。待更