深入理解計算機系統-2(信息存儲)

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進制數
無符號整數範圍  2w1 到 0
有符號整數範圍 2w112w1

java中全部都是有符號數
補碼的表示

B2Tw(x)=xw12w1+i=0w2xi2i

B2Tw([1111])=123+122+121+120

即將字的最高位解釋爲負權
注意,補碼對於任意一個數都是唯一表示的。

在C與java中數的表示範圍的差別

  • C中各種類型的表示範圍定義在<limits.h>中,包括INT_MAX INT_MIN 以及UINT_MAX。 而在<stdint.h>定義了與實現有關的類型, 包含uint16_t之類的,這樣在一定成都上避免了移植的問題。
  • java中不存在移植的問題,不管在什麼機器上,其表示的範圍與標準64位機器的類型字長一致。

有符號數和無符號數之間的互相轉換

對於大多數C語言的實現來說,處理同樣字長的有符號數和無符號數之間的轉換規則是:數值可能改變,但是在系統內存儲的位模式不變。在數值上的改變是:
非負數不變,負數轉變爲大的正數(+2w
這裏寫圖片描述

這裏寫圖片描述


2.3 無符號數截斷的結果

  • 原本w位的無符號數變爲k位,數值上
    B2Uk[xk1,xk2,,x0]=B2Uw([xw1,xw2,,x0])modxk
  • 補碼數字的截斷結果是
    B2Tk[xk1,xk2,,x0]=B2Tk(B2Uw([xw1,xw2,,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 需要加2w 之後與i比較,所以數組要越界。

建議

1.大部分時候,我們不要使用無符號數,因爲程序之間存在的隱式有符號數向無符號數的轉換會導致錯誤和漏洞,我們所有的遍歷都用有符號數去解決,多加一些數組越界的判斷。
2.對於我們僅僅把字看做位的集合,沒有任何數字意義的時候,比如我們利用位作爲標誌flag的時候,或者作爲地址的時候,我們可以採用無符號數,這樣也更加直觀

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章