天天看點

來,想一下:x/2 在什麼時候不等于 x>>1?

地球人都知道,在計算機的世界,乘法和除法可以使用移位來實作,例如下面的兩條等式:

x * 2 ≡ x << 1

x / 2 ≡ x >> 1

但實際上,有時候事情并不是你想的那樣。在C語言标準中,沒有要求有符号整數的内部表示為2的補碼。

在計算機中,對于一個正數會有一個統一的表示法,但如果這個數字是一個負數,則它可以有不同的表示。

如果 x 是一個負數,那麼,x * 2 和 x << 1 在符号/量級系統上完全不同。

但是,Win32 需要執行在一台基于二進制補碼的硬體系統上,在這種情況下,第一個等價 x * 2 ≡ x << 1 确實總是正确的。當然,編譯器可以自由地識别這一點,并重寫你的乘法或移位運算。 事實上,它很可能這樣做,因為 x + x 比乘法或移位更容易配對。 移位操作或乘以二可能會被重寫為更接近 add eax,eax 指令的東西。 至于第二個所謂的等價式,C 語言規範最初沒有規定負數除以正數是四舍五入還是四舍五入為零,但在1999年,規範被修訂為要求四舍五入到零。 此外,未指定負值右移的結果,是以如果 x 為負值,表達式 x >> 1 具有未指定的結果。

即使你假設移位用符号位填充,如果 x 為負數,移位和除法的結果也不同。

(-1) / 2 ≡ 0

(-1) >> 1 ≡ -1

這個故事的寓意

如果你想做什麼,就請明确地告訴編譯器我要做什麼。

如果要你想除以2,請寫”/2″,而不是”>>1″。

總結

我一直沒弄明白移位的細節,總是需要用到的時候,拿出一張紙,用筆來畫出移位的示意圖。

我的大腦,還是比不過你CPU啊。那本<<深入了解計算機系統>>,我還得再拿出來讀讀。

最後