有符号整数的相减,溢出规则为:函数
y=a-b性能
(1)a,b同号时,y必定不会溢出。spa
(2)若 a>=0 && b<0 ,则当 y<=0 时溢出。3d
(3)若 a<=0 && b>=0,则当y>=0时溢出。指针
当a != b时, a - b 不等于0。调试
因此a,b异号,y,b同号便可断定为溢出。blog
首先先定义两个整型变量x,y,计算出他们的位数,而后计算x - y的值,将三个值右移到符号位,比较a,b是否异号,y,b是否同号。进程
int tsub_ovf(int x, int y) { int w = sizeof(int)<<3;//左移三位至关于乘以2^3,4*8=32位 int t = x - y; x>>=(w-1);//右移31位,只剩符号位 y>>=(w-1); t>>=(w-1); return (x != y) && (y == t); }
计算5*x/8至关于计算((x<<2) + x) >> 3,要舍入x为负数时的状况。v8
咱们假设x的位模式为[b(w-1), b(w-2), ... , b(0)]class
计算[b(w-1),b(w-2),b(w-3), ... ,b(0), 0, 0] + [b(w-1),b(w-2),...,b(2), b(1), b(0)] ,而后右移三位,因此咱们能够忽略下方的b(1),b(0)。
因此计算(x<<2) + x,再右移一位,可是(x<<2) + x可能也会溢出,因此计算(x>>3) + (x>>1),这样就不会溢出了。看看b(0)+b(2)会不会产生进位,若是产生进位,则再加一。
最后考虑负数的舍入。负数向0舍入的条件是x<0 && ((x<<2)+x 的后三位不全为0)。知足舍入条件的话,结果再加1。加法后三位不全为0等价为x后三位不全为0。
int mul5div8(int x) { int b0 = x&1, b2 = (x>>2)&1; int ans = (x>>3) + (x>>1); int w = sizeof(int)<<3; ans += (b0&b2); ans += ((x>>(w-1)) && (x&7)); return ans; }
A.π的二进制数表示为:0 10000000 10010010000111111101011,
它表示的二进制小数值为:11.0010010000111111101011
B.根据2.82,可知1/7的表示为0.001001[001]...,
因此22/7为11.001001001001001[001]...
C.从第9位开始不一样。
4行
8行
abc或者bac。c确定在a和b以后。
由于fork函数只被调用一次,可是会返回两次:父进程返回子进程的PID,子进程返回0.若是失败返回-1。
在fork后,子进程和父进程继续执行fork()函数后的指令。
因此不管是先输出a仍是b,c确定在最后面。
下面,咱们调试代码,运行,验证一下结果:
将文件保存在821.c中,并调试:
运行文件,查看结果:
结果是abc,c果真在最后面。
1) a是正确答案,a,对于伙伴系统,若是要申请大小为33的空间,那么须要分配64个空间。若是申请大小为65的空间,那么块大小就须要128,因此最多可能有约50%的空间被浪费。b中,最佳适配要搜索全部空间,因此确定比首次适配要慢一些。c,边界标记主要功能是释放一个块时,能当即和先后空闲块合并。若是空闲块不按顺序排列的话,其实也可以和前一个或者后一个空闲块进行合并,但若是要和先后一块儿合并,可能会有些困难,那须要搜索先后块在空闲链表中的位置,而且删除一个再进行合并。能够参考P576,LIFO方法。d,其实任何分配器均可能有外部碎片,只要剩余的空闲块大小和足够可是单个都不够,就会产生外部碎片。
2)d是正确答案。d, 块大小递增,那么最佳适配法找到的块和首次适配找到的块是同一个,由于最佳适配老是想找一个恰好大于请求块大小的空闲块。a,块大小递减,首次适配很容易找到,因此分配性能会很高。b,最佳适配方法不管怎样,都要搜索全部的链表(除非维护成块大小递增的链表)。c,是匹配的最小的。
3) c是正确答案。c,保守的意思就是全部可能被引用的堆都会被标记,int像指针,因此可能认为它表示的地址是正在被引用的(实际上它只是个int)。
2.74 **
2.78 **
2.90 *
8.11 *
8.12 *
8.21 **
9.19 *
共计:十分