在本教程中,我們將借助示例學(xué)習(xí)C ++中的按位運(yùn)算符。
在C ++中,按位運(yùn)算符對單個(gè)位級別的整數(shù)數(shù)據(jù)執(zhí)行運(yùn)算。這些操作包括測試,設(shè)置或移位實(shí)際位。例如,
a & b; a | b;
這是C ++中包含的6個(gè)按位運(yùn)算符的列表。
運(yùn)算符 | 名稱 | 描述 | 實(shí)例 |
---|---|---|---|
& | 按位與 | 如果同時(shí)存在于兩個(gè)操作數(shù)中,二進(jìn)制 AND 運(yùn)算符復(fù)制一位到結(jié)果中。 | (A & B) 將得到 12,即為 0000 1100 |
| | 按位或 | 如果存在于任一操作數(shù)中,二進(jìn)制 OR 運(yùn)算符復(fù)制一位到結(jié)果中。 | (A | B) 將得到 61,即為 0011 1101 |
^ | 按位異或 | 如果存在于其中一個(gè)操作數(shù)中但不同時(shí)存在于兩個(gè)操作數(shù)中,二進(jìn)制異或運(yùn)算符復(fù)制一位到結(jié)果中。 | (A ^ B) 將得到 49,即為 0011 0001 |
~ | 按位補(bǔ)碼 | 二進(jìn)制補(bǔ)碼運(yùn)算符是一元運(yùn)算符,具有"翻轉(zhuǎn)"位效果,即0變成1,1變成0。 | (~A ) 將得到 -61,即為 1100 0011,一個(gè)有符號二進(jìn)制數(shù)的補(bǔ)碼形式。 |
<< | 左移 | 二進(jìn)制左移運(yùn)算符。左操作數(shù)的值向左移動右操作數(shù)指定的位數(shù)。 | A << 2 將得到 240,即為 1111 0000 |
>> | 右移 | 二進(jìn)制右移運(yùn)算符。左操作數(shù)的值向右移動右操作數(shù)指定的位數(shù)。 | A >> 2 將得到 15,即為 0000 1111 |
這些運(yùn)算符是必需的,因?yàn)橛?jì)算機(jī)CPU中的算術(shù)邏輯單元(ALU)在位級執(zhí)行算術(shù)運(yùn)算。
注意:按位運(yùn)算符只能與 char 和 int數(shù)據(jù)類型一起使用。
當(dāng)且僅當(dāng)兩個(gè)操作數(shù)均為1時(shí),按位AND&運(yùn)算符才返回1。否則,它將返回0。
下表演示了按位AND運(yùn)算符的工作方式。 假設(shè)a和b是兩個(gè)只能取二進(jìn)制值即1和0的操作數(shù)。
a | b | a & b |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
注意:上表被按位AND運(yùn)算符稱為“真值表”。
讓我們看一下兩個(gè)整數(shù)12和25的按位與運(yùn)算:
12 = 00001100 (二進(jìn)制) 25 = 00011001 (二進(jìn)制) //12和25的按位與運(yùn)算 00001100 & 00011001 _________ 00001000 = 8 (十進(jìn)制)
#include <iostream> using namespace std; int main() { //聲明變量 int a = 12, b = 25; cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "a & b = " << (a & b) << endl; return 0; }
輸出結(jié)果
a = 12 b = 25 a & b = 8
在上面的示例中,我們聲明了兩個(gè)變量a和b。在這里,請注意這行,
cout << "a & b = " << (a & b) << endl;
在這里,我們在變量a和b之間執(zhí)行按位與(&)操作。
如果至少有一個(gè)操作數(shù)為1,則按位或(|)運(yùn)算符返回1。否則返回0。
下面的真值表演示了按位OR運(yùn)算符的工作方式。假設(shè)a和b為兩個(gè)只能取二進(jìn)制值(即1或0)的操作數(shù)。
a | b | a | b |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
讓我們看一下兩個(gè)整數(shù)12和25的按位或運(yùn)算:
12 = 00001100 (二進(jìn)制) 25 = 00011001 (二進(jìn)制) //12和25的按位或運(yùn)算 00001100 | 00011001 _________ 00011101 = 29 (十進(jìn)制)
#include <iostream> int main() { int a = 12, b = 25; cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "a | b = " << (a | b) << endl; return 0; }
輸出結(jié)果
a = 12 b = 25 a | b = 29
在按位或中a = 12和b = 25得出29。
當(dāng)且僅當(dāng)其中一個(gè)操作數(shù)為1時(shí),按位XOR ^運(yùn)算符才返回1。但是,如果兩個(gè)操作數(shù)均為0,或者兩個(gè)都為1,則結(jié)果為0。
下面的真值表演示了按位OR運(yùn)算符的工作方式。假設(shè)a和b為兩個(gè)只能取二進(jìn)制值(即1或0)的操作數(shù)。
a | b | a ^ b |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
讓我們看一下兩個(gè)整數(shù)12和25的按位XOR運(yùn)算:
12 = 00001100 (二進(jìn)制) 25 = 00011001 (二進(jìn)制) //12和25的位異或運(yùn)算 00001100 ^ 00011001 _________ 00010101 = 21 (十進(jìn)制)
#include <iostream> int main() { int a = 12, b = 25; cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "a ^ b = " << (a ^ b) << endl; return 0; }
輸出結(jié)果
a = 12 b = 25 a ^ b = 21
a = 12和b = 25的按位異或運(yùn)算得到21。
按位補(bǔ)碼運(yùn)算符是一元運(yùn)算符(僅在一個(gè)操作數(shù)上起作用)。 用~表示,將二進(jìn)制數(shù)字1更改為0,將0更改為1。
需要注意的是,任何整數(shù)N的位補(bǔ)碼等于 -(N+1)。例如
例如整數(shù)35。按照規(guī)則,35的按位補(bǔ)碼應(yīng)為-(35 +1)= -36。現(xiàn)在,讓我們看看是否得到正確的答案。
35 = 00100011 (二進(jìn)制) // 使用按位補(bǔ)碼運(yùn)算符 ~ 00100011 __________ 11011100
在上面的示例中,我們得出00100011(35)的按位補(bǔ)碼為11011100。在這里,如果將結(jié)果轉(zhuǎn)換為十進(jìn)制,則得到220。
但是,需要注意的是,我們不能直接將結(jié)果轉(zhuǎn)換為十進(jìn)制,從而獲得所需的輸出。這是因?yàn)槎M(jìn)制結(jié)果11011100也相當(dāng)于-36。
為了理解這一點(diǎn),我們首先需要計(jì)算-36的二進(jìn)制輸出。我們使用2的補(bǔ)數(shù)來計(jì)算負(fù)整數(shù)的二進(jìn)制數(shù)。
在二進(jìn)制算術(shù)中,1的補(bǔ)碼將0更改為1,將1更改為0。 而且,如果我們在1的補(bǔ)碼結(jié)果上加1,我們就會得到原始數(shù)字的2的補(bǔ)碼。
例如,
36 = 00100100 (二進(jìn)制) 1的補(bǔ)碼 = 11011011 2的補(bǔ)碼 : 11011011 + 1 _________ 11011100
在這里,我們可以看到36的2的補(bǔ)碼(即-36)是11011100。 該值相當(dāng)于35的按位補(bǔ)碼。
因此,我們可以說35的位補(bǔ)碼是-36。
#include <iostream> int main() { int num1 = 35; int num2 = -150; cout << "~(" << num1 << ") = " << (~num1) << endl; cout << "~(" << num2 << ") = " << (~num2) << endl; return 0; }
輸出結(jié)果
~(35) = -36 ~(-150) = 149
在上面的示例中,我們聲明了兩個(gè)整數(shù)變量num1和num2,并分別用值35和-150初始化它們。
然后我們分別用代碼(~num1)和(~num2)計(jì)算它們的位補(bǔ)碼,并將它們顯示在屏幕上。
35的按位補(bǔ)碼 = - (35 + 1) = -36 即 ~35 = -36 -150的按位補(bǔ)碼 = - (-150 + 1) = - (-149) = 149 即 ~(-150) = 149
這正是我們在輸出中得到的。
C ++編程中有兩個(gè)移位運(yùn)算符:
右移運(yùn)算符 >>
左移運(yùn)算符 <<
右移運(yùn)算符將所有位向右移一定數(shù)量的指定位。用>>表示。
當(dāng)我們向右移動任何數(shù)字時(shí),最低有效位將被丟棄,而最高有效位將被零替換。
從上圖可以看到,我們有一個(gè)4位數(shù)字。當(dāng)我們對其執(zhí)行一位右移操作時(shí),每個(gè)單獨(dú)的位向右移1位。
結(jié)果,最右邊的位被丟棄(Discarded),而最左邊的位保持為空。此空位由0代替(Replacement Bit)。
左移位運(yùn)算符將所有位向左移位一定數(shù)量的指定位。用<<表示。
從上圖可以看到,我們有一個(gè)4位數(shù)字。當(dāng)我們對其執(zhí)行1位左移操作時(shí),每個(gè)單獨(dú)的位向左移1位。
結(jié)果,最左邊的位被丟棄(Discarded),而最右邊的位保持為空。此空位由0代替(Replacement Bit)。
#include <iostream> int main() { //聲明兩個(gè)整數(shù)變量 int num = 212, i; //右移操作 cout << "右移:" << endl; //使用for循環(huán)將num從0位右移到3位 for (i = 0; i < 4; i++) { cout << "212 >> " << i << " = " << (212 >> i) << endl; } //左移操作 cout << "\n左移:" << endl; //使用for循環(huán)將num從0位左移到3位 for (i = 0; i < 4; i++) { cout << "212 << " << i << " = " << (212 << i) << endl; } return 0; }
輸出結(jié)果
右移: 212 >> 0 = 212 212 >> 1 = 106 212 >> 2 = 53 212 >> 3 = 26 左移: 212 << 0 = 212 212 << 1 = 424 212 << 2 = 848 212 << 3 = 1696
從上面程序的輸出,我們可以推斷出,對于任何數(shù)字N,右移運(yùn)算符的結(jié)果都是:
N >> 0 = N N >> 1 = (N >> 0) / 2 N >> 2 = (N >> 1) / 2 N >> 3 = (N >> 2) / 2
等等。
同樣,左移運(yùn)算符的結(jié)果為:
N << 0 = N N << 1 = (N << 0) * 2 N << 2 = (N << 1) * 2 N << 3 = (N << 2) * 2
等等。
因此,我們可以得出結(jié)論,
N >> m = [ N >> (m-1) ] / 2 N << m = [ N << (m-1) ] * 2