我們都知道,數(shù)據(jù)在計算機里是以二進制形式表示的,。在實際問題中,,常常 也有一些數(shù)據(jù)對象的情況比較簡單,只需要一個或幾個二進制位就能夠編碼表示,。如果在一個軟件系統(tǒng)中這種數(shù)據(jù)對象非常多,,用一個基本數(shù)據(jù)類型表示,對計算機 資源是一種浪費,。另一方面,,許多系統(tǒng)程序需要對二進制位表示的數(shù)據(jù)直接操作,例如許多計算機硬件設(shè)備的狀態(tài)信息通常是用二進制位串形式表示的,,如果要對硬 件設(shè)備進行操作,,也要送出一個二進制位串的方式發(fā)出命令。由于C語言的主要設(shè)計目的是面向復(fù)雜的系統(tǒng)程序設(shè)計,,所以它特別提供了對二進制位的操作功能,,稱 為位運算。 位運算應(yīng)用于整型數(shù)據(jù),,即把整型數(shù)據(jù)看成是固定的二進制序列,,然后對這些二進制序列進行按位運算。與其它 高級語言相比,,位運算是C語言的特點之一,。但是由于位運算的應(yīng)用涉及更深入和更廣泛的內(nèi)容,初學(xué)者不必細究,在實際應(yīng)用中可逐步體會其優(yōu)越性,。這部分內(nèi)容 相對比較獨立,,讀者可根據(jù)實際需要選擇學(xué)習(xí)。本書僅對位運算及其應(yīng)用作簡要的介紹,。 3.5.1 位運算符 因為一個二進制位只能取值為0或者1,,所以位運算就是從具有0或者1值的運算對象出發(fā),計算出具有0或者1 值的結(jié)果,。C語言提供了6種基本位運算功能:位否定,、位與、位或,、位異或,、位左移和位右移。其中除位否定是單目運算外,,其余5種均為雙目運算,,6個位運算 符分為4個優(yōu)先級別,參見表3-9,。 表3-9 邏輯運算符 運算符 含義 運算對象個數(shù) 結(jié)合方向 優(yōu)先級 ~ 按位求反 單目運算符 自右向左 1 << 按位左移 雙目運算符 自左向右 2 >> 按位右移 雙目運算符 自左向右 2 & 按位與 雙目運算符 自左向右 3 | 按位或 雙目運算符 自左向右 4 ^ 按位異或 雙目運算符 自左向右 5 說明: ① 位運算的優(yōu)先級是:~→<<,、>>→&→|→^。 ② 位運算的運算對象只能是整型(int)或字符型(char)的數(shù)據(jù),。 ③ 位運算是對運算量的每一個二進制位分別進行操作,。 3.5.2 按位邏輯運算 按位邏輯運算包括:位與、位或,、位異或和位否定等四種運算,。為了幫助讀者理解,,我們設(shè)a和b都是16位二進制整數(shù),,它們的值分別是: a: 1010,1001,0101,0111 b: 0110,0000,1111,1011 為了便于閱讀,a和b中每4位用一個逗號分開,。以下介紹對于a和b的位與,、位或、位異或和位否定等按位邏輯運算,。 1.按位與運算 (&) 按位與是對兩個運算量相應(yīng)的位進行邏輯與,,"&"的運算規(guī)則與邏輯與"&&"相同。 按位與表達式:c=a&b a: 1010,1001,0101,0111 & b: 0110,0000,1111,1011 c: 0010,0000,0101,0011 2.按位或運算(|) 按位或是對兩個運算量相應(yīng)的位進行邏輯或操作,,其運算規(guī)則與邏輯或"||"相同,。 按位或表達式:c=a|b a: 1010,1001,0101,0111 | b: 0110,0000,1111,1011 c: 1110,1001,1111,1111 3.按位異或運算(^) 按位異或運算的規(guī)則是:兩個運算量的相應(yīng)位相同,則結(jié)果為0,,相異則結(jié)果為1,。 即: 0^0=0 0^1=1 1^0=1 1^1=0 按位異或表達式:c=a^b a: 1010,1001,0101,0111 ^ b: 0110,0000,1111,1011 c: 1100,1001,1010,1100 可見,異或運算的含義是:兩個相應(yīng)位的值相異,則結(jié)果為1,,相同則為0,。 4.按位求反運算符(~) 按位求反運算運算規(guī)則是將二進制表示的運算對象按位取反,即將1變?yōu)?,,將0變?yōu)椋薄?/p> 按位異或表達式:c=~a ~ a: 1010,1001,0101,0111 c: 0101,0110,1010,1000 5.按位邏輯運算的應(yīng)用 例3-8:設(shè) int x="7",,求y=~x y=~x=~7=~(0000,0000,0000,0111)=1111,1111,1111,1000=-8 可見,對x的值(7)按位求反結(jié)果恰為-8的補碼表示,,其原因是計算機中有: 整數(shù)求負=整數(shù)求補=按位求反+1 所以:按位求反=整數(shù)求負-1,。 請注意求反運算與單目減和邏輯非運算的區(qū)別: y=-x; 結(jié)果為:y=-7, y=!x; 結(jié)果為:y=0,。 例3-9:用按位與運算屏蔽特定位(將指定位清為0),。 設(shè) n="051652"(八進制數(shù)),計算m=n&0177,,則:m=052,。 n: 0,101,001,110,101,010 & 0177: 0,000,000,001,111,111 m: 0,000,000,000,101,010 經(jīng)過位與運算,將n前9位屏蔽掉,,即截?。畹暮螅肺弧?/p> 例3-10:用按位與運算保留特定位,。 要想將一個變量n的特定位保留下來,,只要設(shè)一個數(shù),使該數(shù)的某些位為1,,這些位是與要保留的n的特定位相對應(yīng)的位,,再將n與該數(shù)按位與。 設(shè) n="011050"(為八進制數(shù),。對應(yīng)的二進制為:0,001,001,000,101,000),,要將n的右起第2、4,、6,、8、10位保留下來,,只要 n="n"&01252,,則有: n: 0,001,001,000,101,000 & 01252: 0,000,001,010,101,010 n: 0,000,001,000,101,000 (n=01050) 注意,,按位與的"&"功能與取地址運算的"&"不同,,盡管兩者采用了相同的符號。 例3-11:用按位或運算將指定的位置為1,。 設(shè):x=061,,y=016,,則z=a|b為: x: 0000,0000,,0011,,0001 | y: 0000,0000,,0000,,1110 z: 0000,0000,,0011,,1111 即將x或y中為1的位的相應(yīng)位置成1,其結(jié)果是z中的后6位為1,。 例3-12:用按位異或運算將某個量的特定位翻轉(zhuǎn),。 要將變量n的特定位翻轉(zhuǎn),即原來為1的變0,,為0的變1,,只要設(shè)一個數(shù),使該數(shù)的某些位為1,,這些位是與n中要翻轉(zhuǎn)的相對應(yīng)的位,,然后將n與該數(shù)進行按位異或運算。 設(shè):a=015,,要將后四位翻轉(zhuǎn),,只要a=a^017,則: a: 0000,,0000,,0011,1101 ^ 017: 0000,,0000,,0011,1111 a: 0000,,0000,,0000,,0010 3.5.3 移位運算 C語言提供了兩個移位運算:左移和右移,,它們是把整數(shù)作為二進制位序列,求出把這個序列左移若干位或者右移 若干位所得到的序列,。左移和右移都是雙目運算,,運算符左邊的運算對象是被左移或右移的數(shù)據(jù),而運算符右邊的運算對象是指明移動的位數(shù),。數(shù)據(jù)左移或右移后空 出來的位置補0,。 左移、右移運算表達式的一般形式為: x << n 或 x >> n 其中x為移位運算對象,是要被移位的量,;n是要移動的位數(shù),。 左移運算的規(guī)則是將x的二進制位全部向左移動n位,將左邊移出的高位舍棄,,右邊空出的位補0,。右移是將x的各二進制位全部向右移動n位,將右邊移出的低 位舍棄,,左邊高位空出要根據(jù)原來量符號位的情況進行補充,,對無符號數(shù)則補0;對有符號數(shù),,若為正數(shù)則補0,,若為負數(shù)則補1。 例如,,設(shè)a=7,,則: b=a<<2 即:b=0000,0111<<2=0001,1100=28 c=a>>2 即:c=0000,0111>>2=0000,0001=1 左移的一個特殊用途是將整數(shù)值乘以2的冪,例如:左移運算表達式1<<4的計算結(jié)果是16,,右移可以用于將整數(shù)值除乘2的冪,。 3.5.4 位運算賦值運算符 位運算符與賦值運算符可以組成以下5種位運算賦值運算符: &=、 |=,、 >>=,、 <<=、 ^= 由這些位運算賦值運算符可以構(gòu)成位運算賦值表達式,。例如: x&=y 相當(dāng)于:x=x&y x<<=2 相當(dāng)于:x=x<<2 x>>=3 相當(dāng)于:x=x>>3 x^=5 相當(dāng)于:x=x^5 |
|