C++ 按位运算符

在C++中,按位运算符对整数数据执行位级别的操作。这些操作包括测试、设置或移位实际的位。例如,

a & b;
a | b;

以下是C++中包含的6个按位运算符的列表。

运算符 描述
& 按位 AND 运算符
| 按位 OR 运算符
^ 按位 XOR 运算符
~ 按位求反运算符
<< 按位左移运算符
>> 按位右移运算符

这些运算符是必需的,因为计算机CPU中的算术逻辑单元(ALU)在位级别执行算术运算。

注意:按位运算符只能与charint数据类型一起使用。


1. C++ 按位与运算符

当且仅当两个操作数都为1时,按位与&运算符才返回1。否则,它返回0

下表演示了按位与运算符的工作原理。设ab为两个只能取二进制值,即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

在上面的示例中,我们声明了两个变量ab。这里,请注意这一行,

cout << "a & b = " << (a & b) << endl;

这里,我们在变量ab之间执行按位与


2. C++ 按位或运算符

如果至少有一个操作数为1,则按位或|运算符返回1。否则,它返回0

下面的真值表演示了按位或运算符的工作原理。设ab为两个只能取二进制值,即1或0的运算符。

a b a | b
0 0 0
0 1 1
1 0 1
1 1 1

让我们看看两个整数1225按位或操作。

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 = 12b = 25按位或得到29


3. C++ 按位异或运算符

当且仅当其中一个操作数为1时,按位异或^运算符才返回1。但是,如果两个操作数都为0,或者都为1,则结果为0

下面的真值表演示了按位异或运算符的工作原理。设ab为两个只能取二进制值,即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 = 12b = 25按位异或得到21


4. C++ 按位求反运算符

按位求反运算符是单目运算符(只作用于一个操作数)。它用~表示,将二进制数字1变为0,将0变为1

Bitwise Complement operation in C++
位补码

需要注意的是,任何整数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

在上面的示例中,我们声明了两个整数变量num1num2,并将它们分别初始化为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++ 右移运算符

右移运算符将所有位向右移动指定的位数。它用>>表示。

当我们向右移动任何数字时,**最低有效位**将被丢弃,而**最高有效位**将被零替换。

One bit Right Shift Operator
单比特右移

从上图可以看出,我们有一个**4位数字**。当我们对其执行**单比特**右移操作时,每个比特向右移动1位。

结果是,最右边的比特被丢弃,而最左边的比特保持空位。这个空位被**0**替换。


6. C++ 左移运算符

左移运算符将所有位向左移动指定的位数。它用<<表示。

One bit left shift Operator
单比特左移

从上图可以看出,我们有一个**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位**表示相比,可以左移的位数要多得多。

你觉得这篇文章有帮助吗?

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战