版權(quán)聲明:本文為 gfson
原創(chuàng)文章,轉(zhuǎn)載請注明出處。
注:作者水平有限,文中如有不恰當之處,請予以指正,萬分感謝。
1. 無符號數(shù)加法和算術(shù)溢出
P97.png
- 檢測無符號數(shù)加法中的溢出
P98-1.png
2. 無符號數(shù)的加法逆元
P98-2.png
3. 補碼加法和溢出
P99.png
- 檢測補碼加法中的溢出
P101-1.png
4. 兩個練習題
P101-2.png
- 答案:
P139.png
在函數(shù)的測試過程中,應(yīng)該考慮 TMin 的情況。
5. 補碼的非
P102-1.png
- 補碼非的位級表示
P102-2.png
P103-1.png
計算補碼非位級表示的兩種方法:
- 對每一位求補,再對結(jié)果加 1。既:-x = ~x + 1。
- 先定位最右邊的 1,將這個 1 的左邊所有位取反。
6. 無符號數(shù)和補碼的乘法
P103-2.png
P104.png
- 練習:
P105.png
P140.png
- 如果需要打印 int64_t 的話,需要使用 %lld 或者:
int64_t t;
printf("%" PRId64"\n", t);
宏 PRId64 在 inttypes.h
中定義。
- 思考:碰到判斷溢出的問題時,可以考慮強制類型轉(zhuǎn)化后值是否會變來判斷。
7. 乘以常數(shù)
P106.png
P107-1.png
P107-2.png
- 可以使用移位和加法運算的組合來替代乘以常數(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ù)除法總是舍入到零,既向下舍入一個正值,向上舍入一個負值。
- 對于無符號數(shù),使用邏輯右移,x >> k 即可表示除以 2 的冪。
- 對于補碼,使用算術(shù)右移:
- x >= 0 時,x >> k 即可表示除以 2 的冪。
- x < 0 時,為了達到向上舍入一個負值的目的,需要在右移之前加上一個偏移量。
加偏移量的原理為:- 對于整數(shù) x 和 y(y > 0),[ x / y ] 上界 = [ (x + y - 1) / y ] 下界。
- 總結(jié),對于使用算術(shù)右移的補碼機器來說:
- C 表達式 ( x < 0 ? x + ( 1 << k ) - 1 : x ) >> k 將會計算數(shù)值 x / 2 x 。
9. 練習題
P110-2.png
- 答案:
P141.png
技巧:
- 表達式 x>>31 產(chǎn)生一個字,如果 x 是負數(shù),這個字全為 1,否則全為 0。
- 通過掩碼
& 0xF
的方式,達到期望的偏置值。
P111.png
- 答案:
P142.png
思考:
- 任何時候需要考慮 TMin 的情況。
- 需要考慮溢出的情況,特別是遇到乘法時。
- 當有符號數(shù)與無符號數(shù)一起運算時,會默認先轉(zhuǎn)化為無符號數(shù)運算,如題中 F 所示。
- 無符號數(shù)和補碼乘法結(jié)果的位級表示是一樣的。既,雖然完整位級表示可能不一樣,但是截斷后的位級表示是一樣的。