作者LPH66 (-858993460)
看板C_and_CPP
標題Re: [問題] 位移運算子的疑問
時間Tue Dec 7 20:41:28 2010
※ 引述《scrush (阿慶)》之銘言:
: 遇到的問題(Question):比如說一般的unsigned 所定義的變數是可以隨便用>>,<<
: 來做除或乘的動作,但變成signed定義時,是不是就不能這樣做了?是會因此改變sign bit
: 的關係?假如程式是這樣寫:
: signed long temp = 0x80000000;
: signed long Out;
: Out = (temp >> 16); <--A
: Out = (temp/65536); <--B
: 請問一下,是B對還是A對?如果B才是正確的,是否有其他方法可以在負數的情況下,使用
: 謝謝!
在 low level 的機器語言裡
右移有兩種 signed shift right 和 unsigned shift right
(x86 的易記指令分別叫做 SAR 和 SHR, shift arithmetic right 和 shift right)
差別在於右移時最高位會不會留著原來的 sign bit
signed shift right (即 x86 的 SAR) 會留著
unsigned shift right (即 x86 的 SHR) 會補 0
也就是 signed shift right 會讓負值依然變成負值
以 0x80000000 >> 1 來說就是這樣:
signed shift
┌┐
│↓
└1→0→0→0→………0→0→0→0
_||_
\/
1 1 0 0 ………0 0 0 0 (0xC0000000)
unsigned shift
0
↓
1→0→0→0→………0→0→0→0
_||_
\/
0 1 0 0 ………0 0 0 0 (0x40000000)
(相對的 左移只有一種 右邊一律補0
雖然 x86 的易記指令也有 SHL 和 SAL 兩個 但做的事完全一樣)
在 C 語言裡 兩個都是 >> 表示 實際上是哪一種則是看左邊是不是 unsigned
左邊是 unsigned 則用 unsigned shift right
左邊是 signed 則用 signed shift right
所以在你的例子裡 A 和 B 是一樣的結果 (都會變成 0xFFFF8000, -32768)
如果想要變成 0x00008000 的話則用 ((unsigned long)temp) >> 16 即可
這也就是為什麼用作 bit-field 的變數/常數通常會宣告成 unsigned 的原因
--
◢ ˊ_▂▃▄▂_ˋ. ◣ ▅▅ ▅▅ ι●╮ █
▄▄▄▄▄
▍
./◤_▂▃▄▂_◥ \'▊ HARUHI █████ <■┘ ▄▄▄▄▄▄▄
▎
⊿ ◤◤◥█◥◥█Δ ISM By-gamejye ¢|\ ▌▌▌▌▌▄▌▌
▏
ζ(▏●‵◥′●▊)Ψ ▏ █
⊿Δ ▄▄▄ ▄▄▄▄
█/|▊ 〃 、 〃▋ |\ ▎ ハルヒ主義 █
▄▄▄█▄▄
◥◥|◣ ‵′ ◢/'◢◢
S.O.S 世界を大いに盛り上げるための涼宮ハルヒの団
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.30.81
推 loveme00835:我記得是用"邏輯移位" & "算術移位" 來區分他們 12/07 20:43
→ LPH66:x86 的易記指令正是這樣分的... SAR 的 A 就是"算術" 12/07 20:49
→ loveme00835:蠻奇怪為啥不是 SLR XD 12/07 20:57
推 purpose:表示一個純粹shift所以用sh吧 12/07 21:01
→ wawi:同意一樓~ 12/07 21:30
推 scrush:感謝LPH66大的精闢講解,小弟我明白了,我也正在使用MCU中 12/07 22:31
→ scrush:遇到這裡有小小的疑惑.... 12/07 22:31