版權(quán)聲明:本文為 gfson 原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處。
注:作者水平有限,文中如有不恰當(dāng)之處,請(qǐng)予以指正,萬分感謝。
1. 無符號(hào)數(shù)加法和算術(shù)溢出

P97.png
- 檢測(cè)無符號(hào)數(shù)加法中的溢出

P98-1.png
2. 無符號(hào)數(shù)的加法逆元

P98-2.png
3. 補(bǔ)碼加法和溢出

P99.png
- 檢測(cè)補(bǔ)碼加法中的溢出

P101-1.png
4. 兩個(gè)練習(xí)題

P101-2.png
- 答案:

P139.png
在函數(shù)的測(cè)試過程中,應(yīng)該考慮 TMin 的情況。
5. 補(bǔ)碼的非

P102-1.png
- 補(bǔ)碼非的位級(jí)表示

P102-2.png

P103-1.png
計(jì)算補(bǔ)碼非位級(jí)表示的兩種方法:
- 對(duì)每一位求補(bǔ),再對(duì)結(jié)果加 1。既:-x = ~x + 1。
- 先定位最右邊的 1,將這個(gè) 1 的左邊所有位取反。
6. 無符號(hào)數(shù)和補(bǔ)碼的乘法

P103-2.png

P104.png
- 練習(xí):

P105.png

P140.png
- 如果需要打印 int64_t 的話,需要使用 %lld 或者:
int64_t t;
printf("%" PRId64"\n", t);
宏 PRId64 在 inttypes.h 中定義。
- 思考:碰到判斷溢出的問題時(shí),可以考慮強(qiáng)制類型轉(zhuǎn)化后值是否會(huì)變來判斷。
7. 乘以常數(shù)

P106.png

P107-1.png

P107-2.png
- 可以使用移位和加法運(yùn)算的組合來替代乘以常數(shù)因子的乘法。
- 大多數(shù)編譯器在只需要少量移位、加法和減法就足夠的時(shí)候才使用這種優(yōu)化。
8. 除以 2 的冪

P108-1.png

P108-2.png

P108-3.png

P108-4.png

P109-1.png

P109-2.png

P109-3.png

P109-4.png

P110-1.png
- 整數(shù)除法總是舍入到零,既向下舍入一個(gè)正值,向上舍入一個(gè)負(fù)值。
- 對(duì)于無符號(hào)數(shù),使用邏輯右移,x >> k 即可表示除以 2 的冪。
- 對(duì)于補(bǔ)碼,使用算術(shù)右移:
- x >= 0 時(shí),x >> k 即可表示除以 2 的冪。
- x < 0 時(shí),為了達(dá)到向上舍入一個(gè)負(fù)值的目的,需要在右移之前加上一個(gè)偏移量。
加偏移量的原理為:- 對(duì)于整數(shù) x 和 y(y > 0),[ x / y ] 上界 = [ (x + y - 1) / y ] 下界。
- 總結(jié),對(duì)于使用算術(shù)右移的補(bǔ)碼機(jī)器來說:
- C 表達(dá)式 ( x < 0 ? x + ( 1 << k ) - 1 : x ) >> k 將會(huì)計(jì)算數(shù)值 x / 2 x 。
9. 練習(xí)題

P110-2.png
- 答案:

P141.png
技巧:
- 表達(dá)式 x>>31 產(chǎn)生一個(gè)字,如果 x 是負(fù)數(shù),這個(gè)字全為 1,否則全為 0。
- 通過掩碼
& 0xF的方式,達(dá)到期望的偏置值。

P111.png
- 答案:

P142.png
思考:
- 任何時(shí)候需要考慮 TMin 的情況。
- 需要考慮溢出的情況,特別是遇到乘法時(shí)。
- 當(dāng)有符號(hào)數(shù)與無符號(hào)數(shù)一起運(yùn)算時(shí),會(huì)默認(rèn)先轉(zhuǎn)化為無符號(hào)數(shù)運(yùn)算,如題中 F 所示。
- 無符號(hào)數(shù)和補(bǔ)碼乘法結(jié)果的位級(jí)表示是一樣的。既,雖然完整位級(jí)表示可能不一樣,但是截?cái)嗪蟮奈患?jí)表示是一樣的。