在C++中,按位运算符对整数数据执行位级别的操作。这些操作包括测试、设置或移位实际的位。例如,
a & b;
a | b;
以下是C++中包含的6个按位运算符的列表。
运算符 | 描述 |
---|---|
& |
按位 AND 运算符 |
| |
按位 OR 运算符 |
^ |
按位 XOR 运算符 |
~ |
按位求反运算符 |
<< |
按位左移运算符 |
>> |
按位右移运算符 |
这些运算符是必需的,因为计算机CPU中的算术逻辑单元(ALU)在位级别执行算术运算。
注意:按位运算符只能与char
和int
数据类型一起使用。
1. C++ 按位与运算符
当且仅当两个操作数都为1时,按位与&
运算符才返回1。否则,它返回0。
下表演示了按位与运算符的工作原理。设a和b为两个只能取二进制值,即1和0的运算符。
a | b | a & b |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
注意:上表被称为按位与运算符的“真值表”。
让我们看看两个整数12和25的按位与操作。
12 = 00001100 (In Binary) 25 = 00011001 (In Binary) //Bitwise AND Operation of 12 and 25 00001100 & 00011001 _________ 00001000 = 8 (In decimal)
示例1:按位与
#include <iostream>
using namespace std;
int main() {
// declare variables
int a = 12, b = 25;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "a & b = " << (a & b) << endl;
return 0;
}
输出
a = 12 b = 25 a & b = 8
在上面的示例中,我们声明了两个变量a和b。这里,请注意这一行,
cout << "a & b = " << (a & b) << endl;
这里,我们在变量a和b之间执行按位与。
2. C++ 按位或运算符
如果至少有一个操作数为1,则按位或|
运算符返回1。否则,它返回0。
下面的真值表演示了按位或运算符的工作原理。设a和b为两个只能取二进制值,即1或0的运算符。
a | b | a | b |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
让我们看看两个整数12和25的按位或操作。
12 = 00001100 (In Binary) 25 = 00011001 (In Binary) Bitwise OR Operation of 12 and 25 00001100 | 00011001 _________ 00011101 = 29 (In decimal)
示例2:按位或
#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;
}
输出
a = 12 b = 25 a | b = 29
a = 12
和b = 25
的按位或得到29
。
3. C++ 按位异或运算符
当且仅当其中一个操作数为1时,按位异或^
运算符才返回1。但是,如果两个操作数都为0,或者都为1,则结果为0。
下面的真值表演示了按位异或运算符的工作原理。设a和b为两个只能取二进制值,即1或0的运算符。
a | b | a ^ b |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
让我们看看12和25这两个整数的按位异或操作。
12 = 00001100 (In Binary) 25 = 00011001 (In Binary) Bitwise XOR Operation of 12 and 25 00001100 ^ 00011001 _________ 00010101 = 21 (In decimal)
示例3:按位XOR
#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;
}
输出
a = 12 b = 25 a ^ b = 21
a = 12
和b = 25
的按位异或得到21
。
4. C++ 按位求反运算符
按位求反运算符是单目运算符(只作用于一个操作数)。它用~
表示,将二进制数字1变为0,将0变为1。

需要注意的是,任何整数N的按位求反等于-(N + 1)。例如,
考虑整数35。根据规则,35的按位求反应为-(35 + 1) = -36。现在,让我们看看我们是否能得到正确答案。
35 = 00100011 (In Binary) // Using bitwise complement operator ~ 00100011 __________ 11011100
在上面的示例中,我们得到35(即00100011)的按位求反是11011100。这里,如果我们把结果转换为十进制,得到220。
然而,需要注意的是,我们不能直接将结果转换为十进制并得到期望的输出。这是因为二进制结果 11011100
也等同于 -36。
要理解这一点,我们首先需要计算-36的二进制输出。我们使用2的补码来计算负整数的二进制。
2 的补码
数字N的2的补码得到-N。
在二进制算术中,1的补码将0变为1,将1变为0。
然后,如果我们向1的补码结果加1,我们得到原始数字的2的补码。
例如,
36 = 00100100 (In Binary) 1's Complement = 11011011 2's Complement : 11011011 + 1 _________ 11011100
这里,我们可以看到36(即-36)的2的补码是11011100。这个值等于我们在上一节中计算的35的按位求反。
因此,我们可以说35的按位求反为-36。
示例4:按位求反
#include <iostream>
int main() {
int num1 = 35;
int num2 = -150;
cout << "~(" << num1 << ") = " << (~num1) << endl;
cout << "~(" << num2 << ") = " << (~num2) << endl;
return 0;
}
输出
~(35) = -36 ~(-150) = 149
在上面的示例中,我们声明了两个整数变量num1和num2,并将它们分别初始化为35
和-150
。
然后我们使用代码(~num1)
和(~num2)
分别计算它们的按位求反,并将它们显示在屏幕上。
The bitwise complement of 35 = - (35 + 1) = -36 i.e. ~35 = -36 The bitwise complement of -150 = - (-150 + 1) = - (-149) = 149 i.e. ~(-150) = 149
这正是我们在输出中得到的结果。
C++ 移位运算符
C++编程中有两个移位运算符
- 右移运算符
>>
- 左移运算符
<<
5. C++ 右移运算符
右移运算符将所有位向右移动指定的位数。它用>>
表示。
当我们向右移动任何数字时,**最低有效位**将被丢弃,而**最高有效位**将被零替换。

从上图可以看出,我们有一个**4位数字**。当我们对其执行**单比特**右移操作时,每个比特向右移动1位。
结果是,最右边的比特被丢弃,而最左边的比特保持空位。这个空位被**0**替换。
6. C++ 左移运算符
左移运算符将所有位向左移动指定的位数。它用<<
表示。

从上图可以看出,我们有一个**4位数字**。当我们对其执行**1比特**左移操作时,每个比特向左移动1位。
结果是,最左边的比特被丢弃,而最右边的比特保持空位。这个空位被**0**替换。
示例5:移位运算符
#include <iostream>
int main() {
// declaring two integer variables
int num = 212, i;
// Shift Right Operation
cout << "Shift Right:" << endl;
// Using for loop for shifting num right from 0 bit to 3 bits
for (i = 0; i < 4; i++) {
cout << "212 >> " << i << " = " << (212 >> i) << endl;
}
// Shift Left Operation
cout << "\nShift Left:" << endl;
// Using for loop for shifting num left from 0 bit to 3 bits
for (i = 0; i < 4; i++) {
cout << "212 << " << i << " = " << (212 << i) << endl;
}
return 0;
}
输出
Shift Right: 212 >> 0 = 212 212 >> 1 = 106 212 >> 2 = 53 212 >> 3 = 26 Shift Left: 212 << 0 = 212 212 << 1 = 424 212 << 2 = 848 212 << 3 = 1696
从上面程序的输出,我们可以推断出,对于任何数字N,右移运算符的结果是
N >> 0 = N N >> 1 = (N >> 0) / 2 N >> 2 = (N >> 1) / 2 N >> 3 = (N >> 2) / 2
等等。
同样,左移运算符的结果是
N << 0 = N N << 1 = (N << 0) * 2 N << 2 = (N << 1) * 2 N << 3 = (N << 2) * 2
等等。
因此,我们可以得出结论:
N >> m = [ N >> (m-1) ] / 2 N << m = [ N << (m-1) ] * 2
按位移位在实际中的应用
在上面的示例中,请注意int
数据类型存储数字为**32位**,即int
值由**32个二进制数字**表示。
然而,我们对按位移位运算符的解释使用了表示为**4位**的数字。
例如,十进制数13可以表示为4位和32位
4-bit Representation of 13 = 1101 32-bit Representation of 13 = 00000000 00000000 00000000 00001101
结果是,13(及任何其他数字)的**按位左移**操作可能因其表示的位数不同而有所不同。
因为在**32位**表示中,与**4位**表示相比,可以左移的位数要多得多。