位與 按位或 按位異或 運算

2021-08-07 15:04:30 字數 4541 閱讀 4720

1. 按位與運算 按位與運算子"&"是雙目運算子。其功能是參與運算的兩數各對應的二進位相與。只有對應的兩個二進位均為1時,結果位才為1 ,否則為0。參與運算的數以補碼方式出現。 

例如:9&5可寫算式如下: 00001001 (9的二進位制補碼)&00000101 (5的二進位制補碼) 00000001 (1的二進位制補碼)可見9&5=1。 

按位與運算通常用來對某些位清0或保留某些位。例如把a 的高八位清 0 , 保留低八位, 可作 a&255 運算 ( 255 的二進位制數為0000000011111111)。 

應用: 

a. 清零特定位 (mask中特定位置0,其它位為1,s=s&mask) 

b. 取某數中指定位 (mask中特定位置1,其它位為0,s=s&mask) 

2. 按位或運算 按位或運算子「|」是雙目運算子。其功能是參與運算的兩數各對應的二進位相或。只要對應的二個二進位有乙個為1時,結果位就為1。參與運算的兩個數均以補碼出現。 

例如:9|5可寫算式如下: 

00001001|00000101 

00001101 (十進位制為13)可見9|5=13 

應用: 

常用來將源運算元某些位置1,其它位不變。 (mask中特定位置1,其它位為0 s=s|mask) 

3. 按位異或運算 按位異或運算子「^」是雙目運算子。其功能是參與運算的兩數各對應的二進位相異或,當兩對應的二進位相異時,結果為1。參與運算數仍以補碼出現,例如9^5可寫成算式如下: 

00001001^00000101 00001100 (十進位制為12) 

應用: 

a. 使特定位的值取反 (mask中特定位置1,其它位為0 s=s^mask) 

b. 不引入第三變數,交換兩個變數的值 (設 a=a1,b=b1) 

目 標 操 作 操作後狀態 

a=a1^b1 a=a^b a=a1^b1,b=b1 

b=a1^b1^b1 b=a^b a=a1^b1,b=a1 

a=b1^a1^a1 a=a^b a=b1,b=a1 

4. 求反運算 

求反運算子~為單目運算子,具有右結合性。 其功能是對參與運算的數的各二進位按位求反。例如~9的運算為: ~(0000000000001001)結果為:1111111111110110 

5. 左移運算 

左移運算子「<<」是雙目運算子。其功能把「<< 」左邊的運算數的各二進位全部左移若干位,由「<<」右邊的數指定移動的位數, 高位丟棄,低位補0。 其值相當於乘2。例如: a<<4 指把a的各二進位向左移動4位。如a=00000011(十進位制3),左移4位後為00110000(十進位制48)。 

6. 右移運算 

右移運算子「>>」是雙目運算子。其功能是把「>> 」左邊的運算數的各二進位全部右移若干位,「>>」右邊的數指定移動的位數。其值相當於除2。 

例如:設 a=15,a>>2 表示把000001111右移為00000011(十進位制3)。對於左邊移出的空位,如果是正數則空位補0,若為負數,可能補0或補1,這取決於所用的計算機系統。移入0的叫邏輯右移,移入1的叫算術右移,turbo c採用邏輯右移。 

main() 

再看一例: 

main() 

浮點數的儲存格式: 

浮點數的儲存格式是符號+階碼(定點整數)+尾數(定點小數) 

seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm 

即1位符號位(0為正,1為負),8位指數字,23位尾數字 

浮點數儲存前先轉化成2的k次方形式,即: 

f = a1*2^k + a2*2^(k-1) + ... + ak +... +an*2^(-m) (ai = , a1 = 1) 

如5.5=2^2 + 2^0 + 2^(-1) 

其中的k就是指數,加127後組成8位指數字 

5.5的指數字就是2+127 = 129 = 10000001 

a2a3.....an就是尾數字,不足23位後補0 

所以5.5 = 01000000101000000000000000000000 = 40a00000 

所以,對浮點數*2、/2只要對8位符號位+、- 即可,但不是左移、右移 

關於unsigned int 和 int 的在位運算上的不同,下面有個cu上的例子描述的很清楚: 

[問題]:這個函式有什麼問題嗎? 

/** 

* 本函式將兩個16位元位的值鏈結成為乙個32位元位的值。 

* 引數:shighbits 高16位 

* slowbits 低16位 

* 返回:32位值 

**/ 

long catenatebits16(short shighbits, short slowbits)  / 

[問題的發現]: 

我們先看如下

測試**: 

/ int main()  / 

執行結果為: 

[shighbits1 + slowbits1] 

lresult = 7fff7bcd 

lresult = 8f127bcd 

lresult = ff127bcd 

嗯,執行很正確嘛……於是我們就放心的在自己的程式中使用起這個函式來了。 

可是忽然有一天,我們的乙個程式無論如何結果都不對!經過n個小時的檢查和除錯,最後終於追蹤到……catenatebits16() !?它的返回值居然是錯的!! 

「鬱悶!」你說,「這個函式怎麼會有問題呢!?」 

可是,更鬱悶的還在後頭呢,因為你把程式中的輸入量作為引數,在乙個簡單的main()裡面單步除錯: 

/ int main()  / 

發現結果竟然是: 

[shighbits1 + slowbits1] 

lresult = 7fff7bcd 

lresult = 8f127bcd 

lresult = 8f127bcd 

[shighbits1 + slowbits2] 

lresult = ffff8bcd //oops! 

lresult = ffff8bcd //oops! 

lresult = ffff8bcd //oops! 

前一次還好好的,後一次就ffff了?x檔案? 

[x檔案的真相]: 

注意那兩個我們用來當作低16位值的slowbits1和slowbits2。 

已知: 

使用 slowbits1 = 0x7bcd 時,函式返回正確的值; 

使用 slowbits2 = 0x8bcd 時,函式中發生x檔案。 

那麼,slowbits1與slowbits2有什麼區別? 

注意了,slowbits1和slowbits2都是short型(而不是unsigned short),所以在這裡,slowbits1代表乙個正數值,而slowbits2卻代表了乙個負數值(因為8即是二進位制1000,slowbits2最高位是1)。 

再看catenatebits16()函式: 

/ long catenatebits16(short shighbits, short slowbits)  / 

如果我們在函式中用 

printf("slowbits = %04x ", slowbits); 

列印傳入的slowbits值,會發現 

slowbits = 0x7bcd 時,列印結果為 

slowbits = 7bcd 

而slowbits = 0x8bcd時,列印結果為 

slowbits = ffff8bcd 

是的,即使用%04x也列印出8位十六進製制。 

因此,我們看出來了: 

當slowbits = 0x8bcd時,函式中 "lresult |= (long)slowbits;" 這一句執行,會先將slowbits轉換為 

0xffff8bcd 

再與lresult做或運算。由於現在lresult的值為 0***xx0000 (其中***x是任何值),所以顯然,無論shighbits是什麼值,最後結果都會是 

0xffff8bcd 

而當slowbits = 0x7bcd時,函式中 "lresult |= (long)slowbits;" 這一句執行,會先將slowbits轉換為 

0x00007bcd 

再與lresult做或運算。這樣做或運算出來的結果當然就是對的。 

也就是說,catenatebits16()在slowbits的最高位為0的時候表現正常,而在最高位為1的時候出現偏差。 

[教訓:在某些情況下作位運算和位處理的時候,考慮使用無符號數值——因為這個時候往往不需要處理符號。即使你需要的有符號的數值,那麼也應該考慮自行在呼叫catenatebits16()前後做轉換——畢竟在位處理中,有符號數值相當詭異!] 

下面這個catenatebits16()版本應該會好一些: 

/ unsigned long catenatebits16(unsigned short shighbits, unsigned short slowbits)  / 

注意其中的 "lresult |= (long)slowbits & 0x0000ffff;"。事實上,現在即使我們把catenatebits16()函式的引數(特別是slowbits)宣告為short,結果也會是對的。 

位運算( 按位與 按位或 異或)

參加運算的兩個數,按二進位制位進行 運算。運算規則 只有兩個數的二進位制同時為1,結果才為1,否則為0。負數按補碼形式參加按位與運算 即 0 0 0 0 1 0,1 0 0,1 1 1。比如10 11 即 0000 1010 0000 1011 0000 1010 所以 10 11 等於10 參加運...

位運算(按位與 按位或 異或)

按位與運算子 參加運算的兩個數,按二進位制位進行 與 運算。運算規則 只有兩個數的二進位制同時為1,結果才為1,否則為0。負數按補碼形式參加按位與運算 即 0 0 0 0 1 0,1 0 0,1 1 1。例 3 5 即 00000011 00000101 00000001 所以 3 5的值為1。按位...

按位與,按位或,異或等運算

參加運算的兩個資料,按二進位制位進行 與 運算。運算規則 0 0 0 0 1 0 1 0 0 1 1 1 即 兩位同時為 1 結果才為 1 否則為0 例如 3 5 即 0000 0011 0000 0101 0000 0001 因此,3 5的值得1。另,負數按補碼形式參加按位與運算。與運算 的特殊用...