有符號整數的相減,溢出規則爲:函數
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 *
共計:十分