前言
CSAPP的内容并没有完全吃透,关于曲老师指定的六月份学习书籍《软件安全分析与应用》已经在网上购买,六月的前一段时间同时学习两本书的内容,后面的时间就学习下一本书的内容。
补码
- tmin
/*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void) {
return 1<<31;
}
- fitsBits
要求:求x是否在n位补码的范围内;
解题思路:x是32位表示,所以最高位在32位,而不是在第n位,所以不能直接右移解决问题,要写几个数字仔细观察,如果是非负数,在n位范围内,应该只有最低n-1位里有1,如果是负数,应该是只有最低n-1位里有0。所以对范围内的数字右移n-1位之后,应该要么是全1,要么是全0,然后这会对它+1,再右移一位,就会变成全0了。
/*
* fitsBits - return 1 if x can be represented as an
* n-bit, two's complement integer.
* 1 <= n <= 32
* Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 2
*/
int fitsBits(int x, int n) {
return !(((x>>(n+(~0)))+1)>>1);
}
- divpwr2
要求:补码除以2的n次.
解题思路:需要给负数加入一个偏差(1«n)-1,判断负数就是看最高位是否为1.
/*
* divpwr2 - Compute x/(2^n), for 0 <= n <= 30
* Round toward zero
* Examples: divpwr2(15,1) = 7, divpwr2(-33,4) = -2
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 2
*/
int divpwr2(int x, int n) {
return (x+(((x>>31)&1)<<n)+(~0)+(!((x>>31)&1)))>>n;
}
- negate
题目比较简单,算是送分题。
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
return ~x+1;
}
- isPositive
要求:判断一个数字是否是正数.
解题思路:因为0不包括在内,所以开头觉得可以直接-1,然后判最高位。但是要考虑到,0xffffffff,-1之后就变成了0x7fffffff,最高位为0了。所以要判,x的最高位为0并且x-1的最高位也为0。
/*
* isPositive - return 1 if x > 0, return 0 otherwise
* Example: isPositive(-1) = 0.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 8
* Rating: 3
*/
int isPositive(int x) {
return !(((x>>31)&1)+(((x+(~0))>>31)&1));
}
- isLessOrEqual
解题思路分类讨论两个数字的符号,如果符号不同,必然y最高位是0,x最高位是1,如果符号相同,直接做减法也不会溢出。
/*
* isLessOrEqual - if x <= y then return 1, else return 0
* Example: isLessOrEqual(4,5) = 1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 24
* Rating: 3
*/
int isLessOrEqual(int x, int y) {
int signx = (x>>31)&1;
int signy = (y>>31)&1;
int signdif = (!signy)&signx;
int signsam = (!(signx^signy))&(((x+(~y))>>31)&1);
return signdif|signsam;
}
- ilog2
要求:x二进制里最高位的1在哪里
解题思路:类似于分治的思想。
int ilog2(int x) {
int ans = 0;
ans = ans + ((!!(x>>(16 + ans)))<<4);
ans = ans + ((!!(x>>(8 + ans)))<<3);
ans = ans + ((!!(x>>(4 + ans)))<<2);
ans = ans + ((!!(x>>(2 + ans)))<<1);
ans = ans + ((!!(x>>(1 + ans)))<<0);
return ans;
}
浮点数
- float_neg
要求:uf是一个浮点数表示,对它符号取反,但是如果uf本来就是NaN,就返回本身。
/*
* float_neg - Return bit-level equivalent of expression -f for
* floating point argument f.
* Both the argument and result are passed as unsigned int's, but
* they are to be interpreted as the bit-level representations of
* single-precision floating point values.
* When argument is NaN, return argument.
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 10
* Rating: 2
*/
unsigned float_neg(unsigned uf) {
unsigned tmp = uf&(0x7fffffff);
unsigned result = uf^(0x80000000);
if(tmp>0x7f800000) result=uf;
return result;
}
结束语
还差最后一个float_i2f没有写出来,这一道题比较困难,打算明天花一天时间将其解出。深刻的感到做实验才是学习CSAPP最好的方法。