來,想一下:x/2 在什么時候不等于 x>>1?
地球人都知道,在計算機的世界,乘法和除法可以使用移位來實現(xiàn),例如下面的兩條等式:x * 2 ≡ x << 1x / 2 ≡ x >> 1
但實際上,有時候事情并不是你想的那樣。在C語言標(biāo)準(zhǔn)中,沒有要求有符號整數(shù)的內(nèi)部表示為2的補碼。在計算機中,對于一個正數(shù)會有一個統(tǒng)一的表示法,但如果這個數(shù)字是一個負(fù)數(shù),則它可以有不同的表示。如果 x 是一個負(fù)數(shù),那么,x * 2 和 x << 1 在符號/量級系統(tǒng)上完全不同。
但是,Win32 需要執(zhí)行在一臺基于二進制補碼的硬件系統(tǒng)上,在這種情況下,第一個等價 x * 2 ≡ x << 1 確實總是正確的。當(dāng)然,編譯器可以自由地識別這一點,并重寫你的乘法或移位運算。 事實上,它很可能這樣做,因為 x + x 比乘法或移位更容易配對。 移位操作或乘以二可能會被重寫為更接近 add eax,eax 指令的東西。 至于第二個所謂的等價式,C 語言規(guī)范最初沒有規(guī)定負(fù)數(shù)除以正數(shù)是四舍五入還是四舍五入為零,但在1999年,規(guī)范被修訂為要求四舍五入到零。 此外,未指定負(fù)值右移的結(jié)果,因此如果 x 為負(fù)值,表達(dá)式 x >> 1 具有未指定的結(jié)果。
即使你假設(shè)移位用符號位填充,如果 x 為負(fù)數(shù),移位和除法的結(jié)果也不同。
(-1) / 2 ≡ 0(-1) >> 1 ≡ -1
這個故事的寓意
如果你想做什么,就請明確地告訴編譯器我要做什么。如果要你想除以2,請寫”/2″,而不是”>>1″。
總結(jié)
我一直沒弄明白移位的細(xì)節(jié),總是需要用到的時候,拿出一張紙,用筆來畫出移位的示意圖。我的大腦,還是比不過你CPU啊。那本<<深入理解計算機系統(tǒng)>>,我還得再拿出來讀讀。