CSAPP大概都过了一遍,但是很多东西不实践一下理解还是不到位,趁这个假期尽量把11个lab做一下。
0x1 bitXor
只用位运算实现一个异或
1 | /* |
思路
~(x&y)
是把x和y中同时为1的位置为0,~(~x&~y)
是把x和y同时为0的位置为0,其他位都是1,然后再把两个相与,组合一下。
0x2 tmin
返回补码中的最小值
1 | /* |
思路
根据补码的规则,只有符号位为1时,这个数最小为-2^31^。
0x3 isTmax
返回1,如果输入的x是补码中的最大值
1 | /* |
思路
首先补码的最大值就是符号位为0,其它位为1,我们要做的就是把这个数转化成0。这个数有个特点就是将这个数+1然后再加自己等于-1,然后再取反就等于0了,但是-1如此操作也可以得到同样的结果,所以在x = ~x后面几行就是为了排除这种情况。
0x4 allOddBits
如果所有奇数位都为1,就返回1
1 | /* |
思路
构造出0xaaaaaaaa,然后相与保留该数所有奇数位上为1的位,最后再异或,如果全为0则满足条件。
0x5 negate
返回它的负数
1 | /* |
思路
思路,变负就是按位取反再+1.
0x6 isAsciiDignit
判断输入的ascii值是否大于等于字符0的小于等于字符9的
1 | /* |
思路
- lower是加上比0x30小会是负数的数字
- higher是加上比0x39大的数会是负数的数字
- 最后看看lower和higher是否同时满足条件
0x7 conditional
用位运算符实现三目运算
1 | /* |
思路
先把x转化成真值0或者1,然后注意0和1的特性,0取负以后还是0,1取负以后是-1也就是全1。最后用0和全1对y和z进行选择。
0x8 isLessOrEqual
判断参数1是否小于等于参数2
1 | /* |
思路
分两种情况:
- x和y符号不一样,那么x如果是负号的话就可以返回1
- x和y符号一样,那么就看y-x的符号是正是负
0x9 logicalNeg
实现逻辑非
1 | /* |
思路
还是利用0的特性,只有0和它的补码符号位相与为全零,其它的符号位都会为1。这里+1是考虑到了最小值的特点,它和它的补码符号位都为1。
0x10 howManyBits
该数最少用几个位的补码就可以表示
1 | /* howManyBits - return the minimum number of bits required to represent x in |
思路
- 如果是一个正数,那么只要找到它最高的那个1,然后再加上一个符号位就行了
- 如果是一个负数,那么找到它最高位的0然后再加上一个符号位就行,因为从符号位往右到第一个0的1都没意义。
- 所以如果x是正数,则不变,如果x是负数就给x取反
- 然后依次缩小范围,返回结果。
浮点数简介
IEEE 浮点标准用 V=(-1)^s^M2^E^的形式表示一个数
- 符号, s 决定这个数是正数(s = 0),还是负数(s = 1)
- 尾数 M 是一个二进制小数, 它的范围是 1 ~ 2-e,(标准化数)或者是0 ~ 1-e(非标准化数)
- 阶码 E 的作用是对浮点数加权
单精度浮点格式 s=1位,E=8位,M=23位
双精度浮点格式 s=1位,E=11位, M=52位
0x11 floatScale2
求2乘一个浮点数
1 | //float |
思路
- 如果是非规格化数,直接乘2返回
- 如果是无穷大或者NaN,返回原值
- 再判断乘2后有没有溢出,如果没有溢出就返回更改exp后的uf
- 如果有溢出就返回无穷大
0x12 floatFloat2Int
浮点数转整数
1 | /* |
思路
- 首先考虑特殊情况,如果是0则返回0
- 如果直接阶码部分就溢出了就返回 0x80000000
- 如果是小于0的也返回0(因为尾码的部分肯定不会大于2)
- 然后判断结果跟原来符号一样不一样
- 不一样的话,然后溢出是一种情况
- 原来是负数也是一种情况
0x13 floatPower2
求2.0^x^
1 | /* |
思路
就直接改exp的值呗,把exp改成x+127就行,再看看是不是无穷大,是不是0就行了。
尾数部分全0,代表1.