地球人都知道,在計算機的世界,乘法和除法可以使用移位來實現,例如下面的兩條等式:x * 2 ≡ x << 1x / 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啊。那本<<深入理解計算機系統>>,我還得再拿出來讀讀。
最後Raymond Chen的《The Old New Thing》是我非常喜歡的博客之一,裡面有很多關于Windows的小知識,對于廣大Windows平台開發者來說,确實十分有幫助。本文來自:《When is x/2 different from x>>1?》
,
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!