亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

C語言中的位運算

2019-11-17 05:13:57
字體:
來源:轉載
供稿:網友

  在計算機程序中,數據的位是可以操作的最小數據單位,理論上可以用“位運算”來完成所有的運算和操作。一般的位操作是用來控制硬件的,或者做數據變換使用,但是,靈活的位操作可以有效地提高程序運行的效率。C語言提供了位運算的功能, 這使得C語言也能像匯編語言一樣用來編寫系統程序。

  位運算符C語言提供了六種位運算符:

  & 按位與
   按位或
  ^ 按位異或
  ~ 取反
  << 左移
  >> 右移

  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。參與運算的兩個數均以補碼出現。

   例如:95可寫算式如下:

0000100100000101
00001101 (十進制為13)可見95=13
應用:
常用來將源操作數某些位置1,其它位不變。 (mask中特定位置1,其它位為0 s=smask)

  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(){
 unsigned a,b;
  scanf("%d",&a);
 b=a>>5;
 b=b&15;
 printf("a=%d b=%d ",a,b);
}

  再看一例:

main(){
 char a='a',b='b';
 int p,c,d;
 p=a;
 p=(p<<8)b;
 d=p&0xff;
 c=(p&0xff00)>>8;
 printf("a=%d b=%d c=%d d=%d ",a,b,c,d);
}



浮點數的存儲格式:

浮點數的存儲格式是符號+階碼(定點整數)+尾數(定點小數)
SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM
即1位符號位(0為正,1為負),8位指數位,23位尾數位
浮點數存儲前先轉化成2的k次方形式,即:
f = A1*2^k + A2*2^(k-1) + ... + Ak +... +An*2^(-m) (Ai = {0, 1}, 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)
{
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 + sLowBits1]
lResult = 7fff7bcd
lResult = 8f127bcd
lResult = ff127bcd

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

可是忽然有一天,我們的一個程序無論如何結果都不對!經過n個小時的檢查和調試,最后終于追蹤到……CatenateBits16() !?它的返回值居然是錯的?。?br />
“郁悶!”你說,“這個函數怎么會有問題呢???”

可是,更郁悶的還在后頭呢,因為你把程序中的輸入量作為參數,在一個簡單的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 + 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)
{
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位值放入32位值的低16位 */
lResult = (long)sLowBits & 0x0000FFFF;

return lResult;
}
/////////////////////////////////////////////////

注重其中的 "lResult = (long)sLowBits & 0x0000FFFF;"。事實上,現在即使我們把CatenateBits16()函數的參數(非凡是sLowBits)聲明為short,結果也會是對的。

假如有一天你把一只兔子扔給一只老虎,老虎把兔子吃了,第二天把一只老鼠扔給它,它又吃了,那么說明第一天你看錯了:它本來就是一只貓。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美色videos| 国产成人福利视频| 亚洲香蕉成视频在线观看| 日韩欧美极品在线观看| 一区二区三区日韩在线| 91九色在线视频| 国产精品老女人精品视频| 久久天天躁狠狠躁夜夜av| 91精品久久久久久久久久入口| 国产丝袜视频一区| 久久综合五月天| 91成人天堂久久成人| 国产欧美久久一区二区| 在线电影欧美日韩一区二区私密| 亚洲福利视频二区| 亚洲天堂av在线免费| 国产亚洲精品久久久久久777| 国产欧美亚洲精品| 日韩成人av在线| 国语自产精品视频在免费| 国产成人综合一区二区三区| 国产亚洲成精品久久| 成人免费网站在线看| 国产在线精品一区免费香蕉| 久久色精品视频| 国产热re99久久6国产精品| 欧洲精品在线视频| 欧美成人精品在线视频| 亚洲影院色无极综合| 日韩在线视频中文字幕| 这里只有精品在线播放| 国产精品av免费在线观看| 91产国在线观看动作片喷水| 国产成人精品电影久久久| 日韩精品久久久久久福利| 亚洲日本成人网| 亚洲一区二区三区在线视频| 成人黄色中文字幕| 亚洲视屏在线播放| 国产精品免费久久久久影院| 亚洲新声在线观看| 97高清免费视频| 亚洲综合在线做性| 91在线视频一区| 91欧美激情另类亚洲| 九九久久久久99精品| 亚洲成年网站在线观看| 国产国语刺激对白av不卡| 高清亚洲成在人网站天堂| 一区三区二区视频| 国产日产久久高清欧美一区| 国产亚洲一级高清| 在线精品国产成人综合| 中文字幕一区二区精品| 日韩精品免费观看| 久久久久久国产免费| 7m精品福利视频导航| 欧美激情视频播放| 国产成人自拍视频在线观看| 亚洲一区二区三区视频| 97人洗澡人人免费公开视频碰碰碰| 国产日韩欧美中文在线播放| 亚洲va电影大全| 精品国产一区二区三区久久狼5月| 96国产粉嫩美女| 欧美日韩国产中字| 亚洲在线一区二区| 欧美极品xxxx| 欧美成人网在线| 亚洲男人第一网站| 国产日韩av在线| 欧美激情在线一区| 亚洲国产成人精品久久久国产成人一区| 精品国产乱码久久久久久婷婷| 欧美一区二区三区四区在线| 亚洲人成77777在线观看网| 国产精品美女呻吟| 国产精品成人va在线观看| 日韩在线视频免费观看| 国产精品高潮呻吟久久av黑人| 97久久精品人人澡人人爽缅北| 国产精品美女视频网站| 欧美午夜www高清视频| 92国产精品久久久久首页| 伊人久久久久久久久久久久久| 色播久久人人爽人人爽人人片视av| 久久久精品一区二区三区| 久久精品中文字幕一区| 欧美激情亚洲激情| 国内精品久久久久影院 日本资源| 中文字幕亚洲无线码a| 国产精品情侣自拍| 久久不射热爱视频精品| 亚洲精品成a人在线观看| 91久久国产婷婷一区二区| 午夜欧美不卡精品aaaaa| 日韩av一卡二卡| 久久综合亚洲社区| 91精品国产91久久久久久| 91亚洲精华国产精华| 久久成人综合视频| 欧美大奶子在线| 国模视频一区二区三区| 欧美国产日韩一区| 色婷婷综合成人av| 欧美午夜宅男影院在线观看| 精品国产乱码久久久久酒店| 久久精品视频在线| 亚洲一级黄色片| 国产一区av在线| 精品国产91久久久久久| 日韩免费观看在线观看| 国产精品av在线播放| 国产在线视频2019最新视频| 欧美裸体xxxx| 国产精品成人一区二区| 久久视频中文字幕| 国产精品福利在线观看网址| 伊人久久男人天堂| 最新91在线视频| 中文亚洲视频在线| 久久免费观看视频| 午夜精品一区二区三区在线视| 精品偷拍各种wc美女嘘嘘| 久久精品电影一区二区| 欧美性受xxxx白人性爽| 亚州av一区二区| 粉嫩av一区二区三区免费野| 亚州国产精品久久久| 亚洲乱码av中文一区二区| 日本久久亚洲电影| 亚洲精品电影在线观看| 色哟哟亚洲精品一区二区| 日韩av最新在线| 中文精品99久久国产香蕉| 亚洲爱爱爱爱爱| 伊人伊成久久人综合网小说| 91性高湖久久久久久久久_久久99| 欧美中文在线观看国产| 日本成人免费在线| 亚洲精品91美女久久久久久久| 亚洲黄一区二区| 久久久91精品| 国产精品美女久久久免费| 国产精品毛片a∨一区二区三区|国| 日韩av免费在线观看| 日韩在线观看免费高清| 久久久视频免费观看| 97在线免费视频| 国产69精品99久久久久久宅男| 国产小视频国产精品| 国产在线视频一区| 亚洲字幕在线观看| 日韩免费看的电影电视剧大全| 91精品久久久久久综合乱菊| 国产精品福利在线观看| 日韩成人免费视频| 久久久97精品| 97在线看免费观看视频在线观看| 日韩精品免费综合视频在线播放| 国产一区私人高清影院| 欧美国产精品人人做人人爱| 欧美超级免费视 在线| 综合国产在线观看|