位操作運算符.doc_第1頁
位操作運算符.doc_第2頁
位操作運算符.doc_第3頁
位操作運算符.doc_第4頁
位操作運算符.doc_第5頁
已閱讀5頁,還剩15頁未讀, 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

按位與運算 按位與運算符&是雙目運算符。其功能是參與運算的兩數各對應的二進位相與。只有對應的兩個二進位均為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。參與運算數仍以補碼出現,例如95可寫成算式如下: 0000100100000101 00001100 (十進制為12) 應用: a. 使特定位的值取反 (mask中特定位置1,其它位為0 s=smask) b. 不引入第三變量,交換兩個變量的值 (設 a=a1,b=b1) 目 標 操 作 操作后狀態 a=a1b1 a=ab a=a1b1,b=b1 b=a1b1b1 b=ab a=a1b1,b=a1 a=b1a1a1 a=ab a=b1,b=a1 4. 求反運算 求反運算符為單目運算符,具有右結合性。 其功能是對參與運算的數的各二進位按位求反。例如9的運算為: (0000000000001001)結果為:1111111111110110 5. 左移運算 左移運算符“”是雙目運算符。其功能把“ ”左邊的運算數的各二進位全部左移若干位,由“”右邊的數指定移動的位數, 高位丟棄,低位補0。 其值相當于乘2。例如: a”是雙目運算符。其功能是把“ ”左邊的運算數的各二進位全部右移若干位,“”右邊的數指定移動的位數。其值相當于除2。 例如:設 a=15,a2 表示把000001111右移為00000011(十進制3)。對于左邊移出的空位,如果是正數則空位補0,若為負數,可能補0或補1,這取決于所用的計算機系統。移入0的叫邏輯右移,移入1的叫算術右移,Turbo C采用邏輯右移。main() unsigned a,b; printf(input a number: ); scanf(%d,&a); b=a5; b=b&15; printf(a=%d b=%d ,a,b); 再看一例:main() char a=a,b=b; int p,c,d; p=a; p=(p8; printf(a=%d b=%d c=%d d=%d ,a,b,c,d); 浮點數的存儲格式: 浮點數的存儲格式是符號+階碼(定點整數)+尾數(定點小數)SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM即1位符號位(0為正,1為負),8位指數位,23位尾數位浮點數存儲前先轉化成2的k次方形式,即:f = A1*2k + A2*2(k-1) + . + Ak +. +An*2(-m) (Ai = 0, 1, A1 = 1)如5.5=22 + 20 + 2(-1)其中的k就是指數,加127后組成8位指數位5.5的指數位就是2+127 = 129 = 10000001A2A3.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)long lResult = 0; /* 32位值的臨時變量*/* 將第一個16位值放入32位值的高16位 */lResult = sHighBits;lResult = 16;/* 清除32位值的低16位 */lResult &= 0xFFFF0000;/* 將第二個16位值放入32位值的低16位 */lResult |= (long)sLowBits;return lResult;/問題的發現:我們先看如下測試代碼:/int main()short sHighBits1 = 0x7fff;short sHighBits2 = 0x8f12;unsigned short usHighBits3 = 0xff12;short sLowBits1 = 0x7bcd; long lResult = 0;printf(sHighBits1 + sLowBits1 ;lResult = CatenateBits16(sHighBits1, sLowBits1);printf(lResult = %08x , lResult, lResult);lResult = CatenateBits16(sHighBits2, sLowBits1);printf(lResult = %08x , lResult, lResult);lResult = CatenateBits16(usHighBits3, sLowBits1);printf(lResult = %08x , lResult, lResult); /運行結果為:sHighBits1 + sLowBits1lResult = 7fff7bcdlResult = 8f127bcdlResult = ff127bcd嗯,運行很正確嘛于是我們就放心的在自己的程序中使用起這個函數來了??墒呛鋈挥幸惶?,我們的一個程序無論如何結果都不對!經過n個小時的檢查和調試,最后終于追蹤到CatenateBits16() ?。克姆祷刂稻尤皇清e的!“郁悶!”你說,“這個函數怎么會有問題呢???”可是,更郁悶的還在后頭呢,因為你把程序中的輸入量作為參數,在一個簡單的main()里面單步調試:/int main()short sHighBits1 = 0x7FFF;short sHighBits2 = 0x8F12;unsigned short usHighBits3 = 0x8F12;short sLowBits1 = 0x7BCD; /你實際使用的參數short sLowBits2 = 0x8BCD; /你實際使用的參數long lResult = 0;printf(sHighBits1 + sLowBits1 ;lResult = CatenateBits16(sHighBits1, sLowBits1);printf(lResult = %08x , lResult, lResult);lResult = CatenateBits16(sHighBits2, sLowBits1);printf(lResult = %08x , lResult, lResult);lResult = CatenateBits16(usHighBits3, sLowBits1);printf(lResult = %08x , lResult, lResult); printf( sHighBits1 + sLowBits2 ;lResult = CatenateBits16(sHighBits1, sLowBits2);printf(lResult = %08x , lResult, lResult);lResult = CatenateBits16(sHighBits2, sLowBits2);printf(lResult = %08x , lResult, lResult);lResult = CatenateBits16(usHighBits3, sLowBits2);printf(lResult = %08x , lResult, lResult);return 0;/發現結果竟然是:sHighBits1 + sLowBits1lResult = 7fff7bcdlResult = 8f127bcdlResult = 8f127bcdsHighBits1 + sLowBits2lResult = 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)long lResult = 0; /* 32位值的臨時變量*/* 將第一個16位值放入32位值的高16位 */lResult = sHighBits;lResult = 16;/* 清除32位值的低16位 */lResult &= 0xFFFF0000;/* 將第二個16位值放入32位值的低16位 */lResult |= (long)sLowBits; /注意這一句!return lResult;/如果我們在函數中用printf(sLowBits = %04x , sLowBits);打印傳入的sLowBits值,會發現sLowBits = 0x7bcd 時,打印結果為sLowBits = 7bcd而sLowBits = 0x8bcd時,打印結果為sLowBits = ffff8bcd是的,即使用%04x也打印出8位十六進制。因此,我們看出來了:當sLowBits = 0x8bcd時,函數中 lResult |= (long)sLowBits; 這一句執行,會先將sLowBits轉換為0xffff8bcd再與lResult做或運算。由于現在lResult的值為 0xXXXX0000 (其中XXXX是任何值),所以顯然,無論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)long lResult = 0;/* 將第一個16位值放入32位值的高16位 */lResult = sHighBits;lResult = 16;/* 清除32位值的低16位 */lResult &= 0xFFFF0000;/* 將第二個16位值放入

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論