顧名思義,按位運(yùn)算符允許按照位來操作整型變量。可以把按位運(yùn)算符應(yīng)用于任意signed和unsigned整型,包括char類型。但是,它們通常應(yīng)用于不帶符號(hào)的整型。
這些運(yùn)算符的一個(gè)常見應(yīng)用是在整型變量中使用單個(gè)的位存儲(chǔ)信息。例如標(biāo)記,它用于描述二進(jìn)制狀態(tài)指示符。可以使用一個(gè)位來描述有兩個(gè)狀態(tài)的值:開或關(guān)、男或女,真或假。
也可以使用按位運(yùn)算符處理存儲(chǔ)在一個(gè)變量中的幾個(gè)信息項(xiàng)。例如,顏色值常常記錄為三個(gè)八位值,分別存儲(chǔ)顏色中紅、綠和藍(lán)的強(qiáng)度。這些常常保存到四字
節(jié)變量中的三個(gè)字節(jié)。第四個(gè)字節(jié)也不會(huì)浪費(fèi),包含表示顏色透明度的值。顯然,要處理各個(gè)顏色成分,需要從變量中分離出各個(gè)字節(jié),按位運(yùn)算符就可以做到這一
點(diǎn)。
再看另外一個(gè)例子,假定需要記錄字體的信息,那么,只要存儲(chǔ)每種字體的樣式和字號(hào),以及字體是黑體還是斜體,就可以把這些信息都存儲(chǔ)在一個(gè)二字節(jié)的整型變量中,如圖3-1所示。

圖3-1 把字體數(shù)據(jù)存儲(chǔ)在2個(gè)字節(jié)中
可以使用一位來記錄字體是否為斜體——
1表示斜體,0表示一般。同樣,用另一位來指定字體是否為黑體。使用一個(gè)字節(jié)可以從多達(dá)256種不同的樣式中選擇一個(gè),再用另外5位記錄最多32磅的字
號(hào)。因此,在一個(gè)16位的字中,可以記錄四個(gè)不同的數(shù)據(jù)項(xiàng)。按位運(yùn)算符提供了訪問和修改整數(shù)中單個(gè)位和一組位的便利方式,能方便地組合和分解一個(gè)16位的
字。
3.3.1 移位運(yùn)算符
移位運(yùn)算符可以把整型變量中的內(nèi)容向左或向右移動(dòng)指定的位數(shù)。移位運(yùn)算符和其他按位運(yùn)算符一起使用,可以獲得前面描述的結(jié)果。>>運(yùn)算符把位向右移動(dòng),<<運(yùn)算符把位向左移動(dòng),移出變量兩端的位被舍棄。
所有的按位操作都可以處理任何類型的整數(shù),但本章的例子使用16位的變量,使例子較為簡單。用下面的語句聲明并初始化一個(gè)變量number:
unsigned short number=16387U;
如第2章所述,不帶符號(hào)的字面量應(yīng)在數(shù)字的最后添加字母U或u。
在下面的語句中,對(duì)這個(gè)變量的內(nèi)容進(jìn)行移位,并存儲(chǔ)結(jié)果:
unsigned short result = number <<2; //Shift left two bit positions
移位運(yùn)算符的左操作數(shù)是要移位的值,右操作數(shù)指定要移動(dòng)的位數(shù)。圖3-2列出了該操作的過程。

圖3-2 移位運(yùn)算
從圖3-2可以看出,把數(shù)值16387向左移動(dòng)兩位,得到數(shù)值12。數(shù)值的這種劇烈變化是舍棄高位數(shù)字的結(jié)果。
把數(shù)值向右移動(dòng),可以使用下面的語句:
result = number >>2; //Shift right two bit positions
把數(shù)值16387向右移動(dòng)兩位,得到數(shù)值4096。向右移動(dòng)兩位相當(dāng)于使該數(shù)值除以4。
只要沒有舍棄位,向左移動(dòng)n位就相當(dāng)于把該數(shù)值乘以2的n次方。換言之,就等于把該數(shù)值乘以2n。同樣,向右移動(dòng)n位就相當(dāng)
于把該數(shù)值除以2的n次方。但要注意,變量number向左移位時(shí),如果舍棄了重要的位,結(jié)果就不是我們希望的那樣了。可是,這與乘法運(yùn)算并沒有不同。如
果把2字節(jié)的數(shù)值乘以4,就會(huì)得到相同的結(jié)果,所以向左移位和相乘仍是等價(jià)的。出現(xiàn)問題的原因是相乘的結(jié)果超出了2字節(jié)整數(shù)的取值范圍。
如果需要修改原來的值,可以使用op= 賦值運(yùn)算符。在這種情況下,可以使用>>=或<<=運(yùn)算符。例如:
number >>= 2; // Shift contents of number two positions to the right
這等價(jià)于:
number =number >> 2; // Shift contents of number two positions to the right
這些移位運(yùn)算符跟前面用于輸入輸出的插入和提取運(yùn)算符有可能搞混。從編譯器的角度來看,其含義一般可以從上下文中判斷出來。否則,編譯器就會(huì)生成一個(gè)消息,但用戶需要非常小心。例如,如果輸出變量number向左移動(dòng)兩位的結(jié)果,就應(yīng)編寫下面的代碼:
cout << (number << 2);
其中,括號(hào)是必不可少的。沒有括號(hào),編譯器就會(huì)把移位運(yùn)算符解釋為流插入運(yùn)算符,從而得不到想要的結(jié)果。
按位移動(dòng)帶符號(hào)的整數(shù)
可以把移位運(yùn)算符應(yīng)用于帶符號(hào)和不帶符號(hào)的整型數(shù)。但是,向右移位運(yùn)算符在帶符號(hào)整數(shù)類型的操作隨系統(tǒng)的不同而不同,這取決于編譯器的實(shí)現(xiàn)。在一些情況下,向右移位運(yùn)算符會(huì)在左邊空出來的位上填充0。在其他情況下,符號(hào)位向右移動(dòng),在左邊空出來的位上填充1。
移動(dòng)符號(hào)位的原因是為了保持向右移位和除法運(yùn)算的一致性。可以用char類型的變量來說明這一點(diǎn),解釋其工作原理。假定把value定義為char類型,其初始值為–104(十進(jìn)制):
signed char value=–104;
其二進(jìn)制表示為10011000。使用下面的操作把它向右移動(dòng)兩位:
value >>= 2; //Result 11100110
注釋中顯示了其二進(jìn)制結(jié)果。右邊溢出了兩個(gè)0,因?yàn)榉?hào)位是1,就在左邊空出來的位上填充1。該結(jié)果的十進(jìn)制表示是–26,這正好是value的值除以4的結(jié)果。當(dāng)然,對(duì)于不帶符號(hào)的整數(shù)類型的操作,符號(hào)位不移動(dòng),在左邊空出來的位上填充0。
前面說過,在向右移位負(fù)整數(shù)時(shí),其操作是已定義好的,所以實(shí)現(xiàn)該操作時(shí)不一定要依賴它。因?yàn)樵诖蠖鄶?shù)情況下,使用這些運(yùn)算符是為了進(jìn)行按位操作,此時(shí)維護(hù)位模式的完整性是非常重要的。所以,應(yīng)總是使用不帶符號(hào)的整數(shù),以確保避免高階位的移位。
3.3.2 位模式下的邏輯運(yùn)算
修改整數(shù)值中的位時(shí),可以使用4個(gè)按位運(yùn)算符,如表3-1所示。
表3-1 按位運(yùn)算符
運(yùn) 算 符
|
說 明
|
~
|
這是按位求反運(yùn)算符。它是一個(gè)一元運(yùn)算符,可以反轉(zhuǎn)操作數(shù)中的位,即1變成0,0變成1
|
&
|
這是按位與運(yùn)算符,它對(duì)操作數(shù)中相應(yīng)的位進(jìn)行與運(yùn)算。如果相應(yīng)的位都是1,結(jié)果位就是1,否則就是0
|
^
|
這是按位異或運(yùn)算符,它對(duì)操作數(shù)中相應(yīng)的位進(jìn)行異或運(yùn)算。如果相應(yīng)的位各不相同,例如一個(gè)位是1,另一個(gè)位是0,結(jié)果位就是1。如果相應(yīng)的位相同,結(jié)果位就是0
|
|
|
這是按位或運(yùn)算符,它對(duì)操作數(shù)中相應(yīng)的位進(jìn)行或運(yùn)算。如果兩個(gè)對(duì)應(yīng)的位中有一個(gè)是1,結(jié)果位就是1。如果兩個(gè)位都是0,結(jié)果就是0
|
表3-1中的運(yùn)算符按照其優(yōu)先級(jí)排列,在這個(gè)集合中,按位求反運(yùn)算符的優(yōu)先級(jí)最高,按位或運(yùn)算符的優(yōu)先級(jí)最低。在附錄D的運(yùn)算符優(yōu)先級(jí)表中,按位移動(dòng)運(yùn)算符<<和>>具有相同的優(yōu)先級(jí),它們位于~運(yùn)算符的下面,&運(yùn)算符的上面。
如果以前沒有見過這些運(yùn)算符,就會(huì)問“這非常有趣,但這是為什么?”。下面就將它們用于實(shí)踐。
1. 使用按位與運(yùn)算符
按位與運(yùn)算符一般用于選擇整數(shù)值中特定的一個(gè)位或一組位。為了說明這句話的含義,下面再次使用本節(jié)開頭的例子,利用一個(gè)16位整數(shù)存儲(chǔ)字體的特性。
假定聲明并初始化一個(gè)變量,指定一種12磅字號(hào)、斜體、樣式為6的字體。實(shí)際上,就是圖3-1中的字體。樣式的二進(jìn)制值是00000110,斜體位
是1,黑體位是0,字號(hào)是01100。還有一個(gè)沒有使用的位,需要把font變量的值初始化為二進(jìn)制數(shù)0000 0110 0100 1100。
由于4位二進(jìn)制數(shù)對(duì)應(yīng)于一個(gè)16進(jìn)制數(shù),因此最簡單的方法是以十六進(jìn)制方式指定初 始值:
unsigned short font=0x064C; // Style 6, italic, 12 point
注釋:
在建立像這樣的位模式時(shí),十六進(jìn)制表示法要比十進(jìn)制表示法更合適。
要使用字號(hào),需要從font變量中提取它,這可以使用按位與運(yùn)算符來實(shí)現(xiàn)。只有當(dāng)兩個(gè)位都是1時(shí),按位與運(yùn)算符才會(huì)產(chǎn)生1,所以可以定義一個(gè)值,在
將定義字號(hào)的位和font執(zhí)行按位與操作時(shí)選擇該位。為此,只需定義一個(gè)值,該值在我們感興趣的位上包含1,在其他位上包含0。這種值稱為掩碼,用下面的
語句定義它:
unsigned short size_mask=0x1F; //Mask is 0000 0000 0001 1111
//to select size
font變量的5個(gè)低位表示其字號(hào),把這些位設(shè)置為1,剩余的位設(shè)置為0,這樣它們就會(huì)被舍棄(二進(jìn)制數(shù)0000 0000 0001 1111可轉(zhuǎn)換為十六進(jìn)制數(shù)1F)。
現(xiàn)在可以用下面的語句提取font中的字號(hào)了:
unsigned short size=font & size_mask;
在&操作中,當(dāng)兩個(gè)對(duì)應(yīng)的位是1時(shí),結(jié)果位就是1。任何其他組合起來的結(jié)果就是0。因此組合起來的值如下:
font 0000 0110 0100 1100
size_mask 0000 0000 0001 1111
font & size_mask 0000 0000 0000 1100
把二進(jìn)制值分解為4位一組的形式并不是很重要,這只是易于表示對(duì)應(yīng)的十六進(jìn)制數(shù),看出其中有多少位。掩碼的作用是把最右邊的5位分隔出來,這5位表示點(diǎn)數(shù)(即字號(hào))。
可以使用同樣的方法選擇字體的樣式,只是還需要使用按位移動(dòng)運(yùn)算符把樣式值向右移動(dòng)。可以用下面的語句定義一個(gè)掩碼,選擇左邊的8位,如下所示:
unsigned short style_mask=0xFF00; //Mask is 1111 1111 0000 0000
//for style
用下面的語句獲取樣式值:
unsigned short style=(font & style_mask) >> 8; //Extract the style
該語句的結(jié)果如下:
font 0000 0110 0100 1100
style_mask 1111 1111 0000 0000
font & style_mask 0000 0110 0000 0000
(font & style_mask) >> 8 0000 0000 0000 0110
為表示斜體和黑體的位定義掩碼,并把相應(yīng)的位設(shè)置為1,就很容易把它們分隔出來。當(dāng)然,還需要一種方式來測(cè)試得到的位,這部分內(nèi)容詳見第4章。
按位與運(yùn)算符的另一個(gè)用途是關(guān)閉位。前面介紹的是掩碼中為0的位在結(jié)果中也將輸出0。例如,為了關(guān)閉表示斜體的位,其他的位不變,只需定義一個(gè)掩
碼,使該掩碼中的斜體位為0,其他位為1,再對(duì)font變量和該掩碼進(jìn)行按位與操作即可。實(shí)現(xiàn)此操作的代碼將在按位或運(yùn)算符一節(jié)中介紹。
2. 使用按位或運(yùn)算符
可以使用按位或運(yùn)算符設(shè)置一個(gè)或多個(gè)位。繼續(xù)操作前面的font變量,現(xiàn)在需要設(shè)置斜體和黑體位。用下面的語句可以定義掩碼,選擇這些位:
unsigned short italic=0x40U; //Seventh bit from the right
unsigned short bold=0x20U; //Sixth bit from the right
用下面的語句設(shè)置黑體位:
font |= bold; // Set bold
位的組合如下:
font 0000 0110 0100 1100
bold 0000 0000 0010 0000
font | bold 0000 0110 0110 1100
現(xiàn)在,font變量指定它表示的字體是黑體和斜體。注意這個(gè)操作會(huì)設(shè)置位,而不考慮以前的狀態(tài)。如果以前位的狀態(tài)是開,則現(xiàn)在仍保持開的狀態(tài)。
也可以對(duì)掩碼執(zhí)行按位或操作,設(shè)置多個(gè)位。下面的語句就同時(shí)設(shè)置了黑體和斜體:
font |= bold | italic; //Set bold and italic
該語言很容易讓人選擇錯(cuò)誤的運(yùn)算符。“設(shè)置斜體和黑體”很容易讓人覺得應(yīng)使用&運(yùn)算符,而這是錯(cuò)誤的。對(duì)兩個(gè)掩碼執(zhí)行按位與操作會(huì)得到一個(gè)所有位都是0的值,這不會(huì)改變字體的任何屬性。
如上一節(jié)最后所述,可以使用&運(yùn)算符關(guān)閉位。也就是定義一個(gè)掩碼,把其中要關(guān)閉的位設(shè)置為0,其他位設(shè)置為1。但如何指定這樣的掩碼?如果
要顯式指定它,就需要知道變量中有多少個(gè)字節(jié),如果希望程序可以任何方式移植,這就不很方便。可是,在通常用于打開位的掩碼上使用按位求反運(yùn)算符,就可以
得到這樣的掩碼。在bold掩碼上關(guān)閉黑體位,就可以得到該掩碼:
bold 0000 0000 0010 0000
~bold 1111 1111 1101 1111
按位求反運(yùn)算符的作用是反轉(zhuǎn)原數(shù)值中的每一位,使0變成1,1變成0。無論bold變量占用2個(gè)字節(jié)、4個(gè)字節(jié)還是8個(gè)字節(jié),這都會(huì)生成我們期望的結(jié)果。
提示:
按位求反運(yùn)算符有時(shí)稱為NOT運(yùn)算符,因?yàn)閷?duì)于它操作的每個(gè)位,都會(huì)得到跟開始不同的值。
因此,在關(guān)閉黑體位時(shí),只需對(duì)掩碼bold的反碼和font變量執(zhí)行按位與操作,可用的語句如下所示:
font &= ~bold; //Turn bold off
還可以使用&運(yùn)算符把幾個(gè)掩碼組合起來,再對(duì)結(jié)果跟要修改的變量執(zhí)行按位與操作,將多個(gè)位設(shè)置為0。例如:
font &= ~bold & ~italic; //Turn bold and italic off
這個(gè)語句把font變量中的斜體和黑體位設(shè)置為0。注意這里不需要括號(hào),因?yàn)閪運(yùn)算符的優(yōu)先級(jí)高于&運(yùn)算符。但是,如果不清楚運(yùn)算符的優(yōu)先級(jí),就應(yīng)加上括號(hào),表示希望執(zhí)行的操作。這肯定是無害的,在需要括號(hào)時(shí)還可以正常發(fā)揮作用。
3. 使用按位異或運(yùn)算符
按位異或運(yùn)算符的使用頻率遠(yuǎn)遠(yuǎn)低于&和 |
運(yùn)算符,有關(guān)它的使用例子也比較少。但它的一個(gè)重要應(yīng)用是圖形編程。在屏幕中創(chuàng)建動(dòng)畫的一種方式是繪制一個(gè)對(duì)象,刪除它,再在一個(gè)新位置重新繪制。如果要
求動(dòng)畫很平滑,這個(gè)過程就需要重復(fù)得很快,其中刪除是一個(gè)重要的部分。我們并不想刪除和重新繪制整個(gè)屏幕,因?yàn)檫@非常費(fèi)時(shí),屏幕也會(huì)出現(xiàn)閃爍。最理想的
是,只刪除屏幕上要移動(dòng)的對(duì)象。使用所謂的異或模式就可以做到這一點(diǎn),得到非常平滑的 動(dòng)畫。
異或模式的理念是,在屏幕上用給定的顏色繪制對(duì)象,如果接著用背景色重新繪制它,它就會(huì)消失。如圖3-3所示。

圖3-3 用異或模式繪圖
以異或模式在屏幕上繪制對(duì)象時(shí),每次繪制對(duì)象的顏色會(huì)自動(dòng)在為對(duì)象所選的顏色和背景色之間來回變化。得到這一效果的關(guān)鍵是使用按位異或運(yùn)算符快速而
自動(dòng)地改變顏色。它使用異或運(yùn)算符的一個(gè)特性,即如果對(duì)兩個(gè)值進(jìn)行異或操作,再對(duì)所得的結(jié)果和一個(gè)原始值執(zhí)行異或操作,就會(huì)得到另一個(gè)值。這聽起來很復(fù)
雜,下面就用一個(gè)例子來說明。
假定要在前景色(這里使用紅色)和背景色(白色)之間來回切換。顏色通常用3個(gè)8位值來表示,分別對(duì)應(yīng)于紅、藍(lán)、綠的亮度,存儲(chǔ)在一個(gè)4字節(jié)的整數(shù)
中。通過改變顏色中的紅、藍(lán)和綠的比例,就可以獲得大約1600萬種不同的顏色,包括從白色到黑色之間的所有顏色。純紅色是0xFF0000,這時(shí)紅色成
分設(shè)置為其最大值,其他兩種顏色即藍(lán)色和綠色的成分設(shè)置為0。在相同顏色模式下,綠色就是0xFF00,藍(lán)色是0xFF。在白色中,紅、藍(lán)、綠的成分具有
相同的最大值,即0xFFFFFF。
可以用下面的語句定義表示紅色和白色的變量:
unsigned long red=0XFF0000UL; //Color red
unsigned long white=0XFFFFFFUL; //Color white-RGB all maximum
接著創(chuàng)建一個(gè)掩碼,用于在紅色和白色之間來回切換,并把包含繪圖顏色的變量初始化為紅色:
unsigned long mask=red ^ white; //Mask for switching colors
unsigned long draw_color=red; //Drawing color
變量mask初始化為要切換的兩種顏色的按位異或操作結(jié)果,因此:
red 1111 1111 0000 0000 0000 0000
white 1111 1111 1111 1111 1111 1111
mask(即red ^ white) 0000 0000 1111 1111 1111 1111
如果對(duì)mask和red執(zhí)行異或操作,就會(huì)得到white,如果對(duì)mask和white執(zhí)行異或操作,就會(huì)得到red。因此,使用draw_color中的顏色繪制對(duì)象,就可以通過下面的語句切換顏色:
draw_color ^= mask; //Switch the drawing color
當(dāng)draw_color包含red時(shí),其執(zhí)行過程如下:
draw_color 1111 1111 0000 0000 0000 0000
mask 0000 0000 1111 1111 1111 1111
draw_color ^ mask 1111 1111 1111 1111 1111 1111
顯然,draw_color的值從紅色變?yōu)榘咨T俅螆?zhí)行這個(gè)語句,就會(huì)把顏色改回為紅色:
draw_color^=mask; //Switch the drawing color
其執(zhí)行過程如下:
draw_color 1111 1111 1111 1111 1111 1111
mask 0000 0000 1111 1111 1111 1111
draw_color ^ mask 1111 1111 0000 0000 0000 0000
draw_color又變成了紅色。這個(gè)技術(shù)適用于任意兩種顏色,當(dāng)然它實(shí)際上與特定顏色沒有一點(diǎn)關(guān)系,可以把它用于切換任意一對(duì)整型數(shù)值。
程序示例3.4—— 使用按位運(yùn)算符
下面用一個(gè)例子來試驗(yàn)按位運(yùn)算符,看看它們?nèi)绾我黄鸸ぷ鳌1纠€演示了如何使用異或運(yùn)算符在兩個(gè)值之間切換,以及如何使用掩碼來選擇和設(shè)置各個(gè)位。代碼如下:
//Program 3.4 Using the bitwise operators
#include <iostream>
#include <iomanip>
using std::cout;
using std::endl;
using std::setfill;
using std::setw;
int main() {
unsigned long red=0xFF0000UL; //Color red
unsigned long white=0xFFFFFFUL; //Color white - RGB all maximum
cout << std::hex; //Set hexadecimal output format
cout << setfill('0'); //Set fill character for output
cout << "\nTry out bitwise AND and OR operators.";
cout << "\nInitial value red = "<< setw(8) << red;
cout << "\nComplement ~red = "<< setw(8) <<~ red;
cout << "\nInitial value white = "<< setw(8) << white;
cout << "\nComplement ~ white = "<< setw(8) <<~ white;
cout << "\n Bitwise AND red & white = " << setw(8) << (red & white);
cout << "\n Bitwise OR red | white = " << setw(8) << (red | white);
cout << "\n\nNow we can try out successive exclusive OR operations.";
unsigned long mask=red ^ white;
cout << "\n mask= red ^ white = " << setw(8) << mask;
cout << "\n mask ^ red = " << setw(8) << (mask ^ red);
cout << "\n mask ^ white = " << setw(8) << (mask ^ white);
unsigned long flags=0xFF; //Flags variable
unsigned long bit1mask=0x1; //Selects bit 1
unsigned long bit6mask=0x20; //Selects bit 6
unsigned long bit20mask=0x80000; //Selects bit 20
cout << "\n\nNow use masks to select or set a particular flag bit.";
cout << "\nSelect bit 1 from flags : " << setw(8) << (flags & bit1mask);
cout << "\nSelect bit 6 from flags : " << setw(8) << (flags & bit6mask);
cout << "\nSwitch off bit 6 in flags : " << setw(8) << (flags &= ~bit6mask);
cout << "\nSwitch on bit 20 in flags : " << setw(8) << (flags |= bit20mask);
cout <<endl;
return 0;
}
該例子的輸出如下:
Try out bitwise AND and OR operators.
Initial value red = 00ff0000
Complement ~red = ff00ffff
Initial value white = 00ffffff
Complement ~ white = ff000000
Bitwise AND red & white = 00ff0000
Bitwise OR red | white = 00ffffff
Now we can try out successive exclusive OR operations.
mask= red ^ white =0000ffff
mask ^ red = 00ffffff
mask ^ white =00ff0000
Now use masks to select or set a particular flag bit.
Select bit 1 from flags : 00000001
Select bit 6 from flags : 00000020
Switch off bit 6 in flags : 000000df
Switch on bit 20 in flags : 000800df
例子的說明
本例中添加了對(duì)標(biāo)準(zhǔn)頭文件<iomanip>的#include指令,這個(gè)頭文件在第2章介紹過,因?yàn)榇a將使用操縱程序控制輸出的格式。首先,定義兩個(gè)整數(shù)變量,它們包含的值表示要用于后續(xù)按位運(yùn)算的顏色:
unsigned long red=0xFF0000UL; //Color red
unsigned long white=0xFFFFFFUL; //Color white - RGB all maximum
為了把數(shù)據(jù)顯示為十六進(jìn)制值,可用下面的語句指定:
cout << std::hex; //Set hexadecimal output format
其中hex是一個(gè)操縱程序,它把整數(shù)值的輸出表示為十六進(jìn)制。注意,這是模式化的,該程序以后在標(biāo)準(zhǔn)輸出流中的所有整數(shù)輸出都采用十六進(jìn)制格式。不需要把hex發(fā)送給輸出流cout。如果需要,可以用下面的語句把輸出格式改回為十進(jìn)制:
cout << std::dec; //Set decimal output format
這個(gè)語句使用dec操縱程序,把整數(shù)輸出重新設(shè)置為默認(rèn)的十進(jìn)制表示。注意,把輸出格式設(shè)置為十六進(jìn)制,僅影響整數(shù)值。浮點(diǎn)數(shù)值會(huì)繼續(xù)顯示為一般的十進(jìn)制。
如果在輸出整數(shù)時(shí)加上前導(dǎo)0,就會(huì)使結(jié)果更清晰易懂。用下面的語句設(shè)置這種模式:
cout << setfill('0'); //Set fill character for output
其中setfill()是一個(gè)操縱程序,它把填充字符設(shè)置為括號(hào)中的字符。這也是模式化的,這樣,以后的所有整數(shù)輸出都會(huì)在需要時(shí)使用這個(gè)填充字符。它對(duì)十進(jìn)制和十六進(jìn)制輸出都起作用。如果要用星號(hào)代替該填充字符,則可以使用下面的語句:
cout << setfill('*'); //Set fill character for output
要把填充字符設(shè)置回原來的默認(rèn)值,只需在括號(hào)中使用空格:
cout << setfill(' '); //Set fill character for output
下面的語句顯示red的值及其反碼:
cout << "\nInitial value red = "<< setw(8) << red;
cout << "\nComplement ~red = "<< setw(8) <<~ red;
這里使用第2章介紹的setw()操縱程序,把輸出字段寬度設(shè)置為8。如果所有的輸出值都采用相同的字段寬度,就很容易比較它們。設(shè)置寬度不是模式化的,它只應(yīng)用于跟在字段寬度設(shè)置點(diǎn)后面的下一條語句的輸出。在red和white的輸出中,~運(yùn)算符反轉(zhuǎn)了其操作數(shù)的位。
下面的語句使用按位與以及按位或運(yùn)算符來合并red和white:
cout << "\n Bitwise AND red & white = " << setw(8) << (red & white);
cout << "\n Bitwise OR red | white = " << setw(8) << (red | white);
注意輸出中表達(dá)式的括號(hào)。它們是必需的,因?yàn)?lt;<的優(yōu)先級(jí)高于&和|。沒有括號(hào),該語句就不會(huì)編譯。如果查看一下輸出,就會(huì)看
出它跟這里討論的相同。若對(duì)兩個(gè)值都為1的位執(zhí)行按位與操作,就會(huì)得到1,否則結(jié)果就是0。在對(duì)兩個(gè)位執(zhí)行按位或操作時(shí),除非兩個(gè)位都是0,否則結(jié)果就是
1。
然后,創(chuàng)建一個(gè)掩碼,在通過按位異或運(yùn)算符組合兩個(gè)值時(shí),該掩碼用于反轉(zhuǎn)red和white的值。
unsigned long mask=red ^ white;
如果查看一下mask值的輸出,就會(huì)發(fā)現(xiàn)在兩個(gè)位的值不同時(shí),對(duì)兩個(gè)位執(zhí)行異或操作的結(jié)果是1,在兩個(gè)位的值相同時(shí),該操作的結(jié)果是0。利用異或運(yùn)算符把mask和兩個(gè)顏色值中的一個(gè)組合起來,就會(huì)得到另一個(gè)顏色值。這可以用下面的語句來說明:
cout << "\n mask ^ red = " << setw(8) << (mask ^ red);
cout << "\n mask ^ white = " << setw(8) << (mask ^ white);
最后一組語句演示了如何使用掩碼從一組標(biāo)記位中選擇一個(gè)位。選擇某個(gè)位的掩碼必須使該位的值為1,其他位的值為0。因此,從一個(gè)32位long變量中選擇第1、6和20位的掩碼定義如下:
unsigned long bit1mask=0x1; //Selects bit 1
unsigned long bit6mask=0x20; //Selects bit 6
unsigned long bit20mask=0x80000; //Selects bit 20
要從flags中選擇一個(gè)位,只需對(duì)相應(yīng)的掩碼和flages的值執(zhí)行按位與操作。例如:
cout << "\nSelect bit 6 from flags : " << setw(8) << (flags & bit6mask);
從輸出中可以看到,表達(dá)式(flags & bit6mask)的結(jié)果是只設(shè)置了第6位的整數(shù)。當(dāng)然,如果flages中的第6位為0,該表達(dá)式的結(jié)果就是0。
要關(guān)閉一個(gè)位,需要對(duì)flages變量和一個(gè)掩碼執(zhí)行按位與操作。在該掩碼中,要關(guān)閉的那個(gè)位是0,其他位是1。對(duì)掩碼和對(duì)應(yīng)的位執(zhí)行按位求反操作,也可以關(guān)閉該位。bit6mask就是這樣的一個(gè)掩碼。下面的語句把flags中的第6位關(guān)閉,并顯示結(jié)果:
cout << "\nSwitch off bit 6 in flags : " << setw(8) << (flags &= ~bit6mask);
當(dāng)然,如果第6位已經(jīng)是0,該位就保持不變。要打開一個(gè)位,只需對(duì)flages和一個(gè)掩碼執(zhí)行按位或操作,在該掩碼中,要打開的那個(gè)位是1:
cout << "\nSwitch on bit 20 in flags : " << setw(8) << (flags |= bit20mask);
這個(gè)語句把flags中的第20位設(shè)置為1,并顯示結(jié)果。如果這個(gè)位已經(jīng)是1,該位將保持不變。
4. 輸出操縱程序
把第2章介紹的也算在內(nèi),到目前為止我們已介紹了5個(gè)模式化輸出操縱程序,它們都是在<iostream>頭文件中定義
的:scientific、fixed、dec、hex和oct。表3-2列出所有的其他相似的操縱程序。目前不介紹后兩項(xiàng)中的bool值,它將在第4章
討論。
表3-2 輸出操縱程序
操 縱 程 序
|
執(zhí)行的動(dòng)作
|
dec
|
把整數(shù)值格式化為十進(jìn)制。這是默認(rèn)的表示法
|
hex
|
把整數(shù)值格式化為十六進(jìn)制
|
oct
|
把整數(shù)值格式化為八進(jìn)制
|
left
|
使輸出字段中的值左對(duì)齊,其右端用填充字符填充。默認(rèn)的填充字符是空格
|
right
|
使輸出字段中的值右對(duì)齊,其左端用填充字符填充。這是默認(rèn)的對(duì)齊方式
|
fixed
|
以固定點(diǎn)表示法輸出浮點(diǎn)數(shù)值,即不帶指數(shù)
|
scientific
|
以科學(xué)表示法輸出浮點(diǎn)數(shù)值,即尾數(shù)加指數(shù)的方式。默認(rèn)的模式根據(jù)要顯示的數(shù)值,選擇fixed或scientific表示法
|
showpoint
|
給浮點(diǎn)數(shù)值顯示小數(shù)點(diǎn)和尾部的0
|
noshowpoint
|
與上一個(gè)操縱程序相反。這是默認(rèn)的
|
showbase
|
在八進(jìn)制的輸出前面加上前導(dǎo)0,在十六進(jìn)制的輸出前面加上前導(dǎo)0x或0X
|
noshowbase
|
八進(jìn)制和十六進(jìn)制的輸出中不顯示前綴。這是默認(rèn)的
|
showpos
|
正數(shù)前面加上+號(hào)
|
noshowpos
|
正數(shù)前面不顯示+號(hào),這是默認(rèn)的
|
uppercase
|
在以十六進(jìn)制格式輸出整數(shù)時(shí),給十六進(jìn)制數(shù)字顯示大寫字母A到F。如果設(shè)置了showbase,還要顯示0X。在以科學(xué)計(jì)數(shù)法輸出數(shù)值時(shí),給指數(shù)顯示E,而不是使用小寫字母e
|
nouppercase
|
對(duì)上述項(xiàng)使用小寫字母,這是默認(rèn)的
|
boolalpha
|
把bool值顯示為true和false
|
noboolalpha
|
把bool值顯示為1和0
|
可以一次設(shè)置多種模式,方法是在流中插入多個(gè)操縱程序。例如,如果要把整型數(shù)據(jù)輸出為十六進(jìn)制值,且在輸出字段中左對(duì)齊,就可以使用下面的語句:
std::cout << std::hex << std::left << value;
這個(gè)語句會(huì)把value(以及程序中后續(xù)的所有整數(shù),除非改變了設(shè)置)輸出為左對(duì)齊的十六進(jìn)制數(shù)值。
表3-3列出了需要提供參數(shù)值的輸出操縱程序。
表3-3 需要參數(shù)的輸出操縱程序
操 縱 程 序
|
執(zhí)行的動(dòng)作
|
setfill()
|
把填充字符設(shè)置為參數(shù)指定的字符。默認(rèn)的填充字符是空格
|
setw()
|
把字段寬度設(shè)置為參數(shù)指定的值
|
setprecision()
|
把浮點(diǎn)值的精度設(shè)置為參數(shù)指定的值。精度是輸出中十進(jìn)制數(shù)字的個(gè)數(shù)
|
Tag標(biāo)簽:
c++ ,
按位運(yùn)算符,
與或非