2.1. C語言中的移位運算
這裏有兩種移位操作:算術移位和邏輯移位,其主要差別在於有符號數的負數上。
對於x=00110011而言 y=x>>3
* 邏輯移位 y=00000110
* 算術移位 y=00000110
對於x=10110011而言 y=x>>3
- 邏輯移位 y=00010110
- 算術移位 y=11110110
也就是說:算術右移是在最左端補k個最高有效位的值,而邏輯移位統一補0。
在C語言中,對於無符號數,統一採用邏輯移位,對於有符號數,大部分編譯器採用算術移位。這樣對有符號整數的運算非常有幫助。請保證移位的數量小於計算機存儲的字長。
2.2 整數表示
w位2進制數
無符號整數範圍
有符號整數範圍
java中全部都是有符號數
補碼的表示
即將字的最高位解釋爲負權
注意,補碼對於任意一個數都是唯一表示的。
在C與java中數的表示範圍的差別
- C中各種類型的表示範圍定義在
<
limits.h>
中,包括INT_MAX INT_MIN 以及UINT_MAX。 而在<
stdint.h>
定義了與實現有關的類型, 包含uint16_t之類的,這樣在一定成都上避免了移植的問題。 - java中不存在移植的問題,不管在什麼機器上,其表示的範圍與標準64位機器的類型字長一致。
有符號數和無符號數之間的互相轉換
對於大多數C語言的實現來說,處理同樣字長的有符號數和無符號數之間的轉換規則是:數值可能改變,但是在系統內存儲的位模式不變。在數值上的改變是:
非負數不變,負數轉變爲大的正數(+
2.3 無符號數截斷的結果
- 原本w位的無符號數變爲k位,數值上
B2Uk[xk−1,xk−2,……,x0]=B2Uw([xw−1,xw−2,……,x0])modxk - 補碼數字的截斷結果是
B2Tk[xk−1,xk−2,……,x0]=B2Tk(B2Uw([xw−1,xw−2,……,x0])modxk)
也就是說,先要按無符號數的形式截斷一次,之後再把截斷的結果轉換位補碼
2.4 關於這部分的應用(我的一點理解)
float sum(float a[], unsigned int length)
{
int i;
float result=0;
for(i=0;i<=length-1;i++)
result += a[i];
return result;
}
當我們給length 賦值0的時候,運行這段代碼本應該產生0.0,但是實際運行會出現數組越界的問題,原因如下:
length位無符號數,在執行i<=length-1
的時候,length-1會自動轉爲int類型,首先length-1變爲-1,-1由unsigned int轉爲int 需要加
建議
1.大部分時候,我們不要使用無符號數,因爲程序之間存在的隱式有符號數向無符號數的轉換會導致錯誤和漏洞,我們所有的遍歷都用有符號數去解決,多加一些數組越界的判斷。
2.對於我們僅僅把字看做位的集合,沒有任何數字意義的時候,比如我們利用位作爲標誌flag的時候,或者作爲地址的時候,我們可以採用無符號數,這樣也更加直觀