位运算符


2022年8月17日, Learn eTutorial
2442

在本教程中,我们将借助示例学习 C++ 中的位运算符。

C++ 中的位运算符对整数数据进行单个位级别的操作。这些操作包括位测试、位设置和位移位。

例如

a & b;
a | b;

为了在 C++ 中对单个位执行操作,使用了位运算符。它们只兼容 char 和 int 数据类型。C++ 中主要有 6 种位运算符

operator 其描述
& 按位与
| 按位或
^ 按位异或
~ 按位一补码
<<  按位左移
>>  按位右移

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

C++ 中的按位与运算符

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

下表显示了按位与运算符的操作。设 a 和 b 是两个只接受二进制值(即 1 和 0)的操作数。

Bitwise AND Operator in C++ -Truth Table

上面给出的表格被称为按位与运算符的“真值表”。

让我们检查两个整数 15 和 36 的按位与操作

Bitwise AND Operator in C++ -Truth Table

按位与操作的示例


#include <iostream>
using namespace std;

int main() {
    // declare variables
    int a = 15, b = 36;

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

    return 0;
}

输出


a = 15
b = 36
a & b = 4

在前面的示例中,我们声明了两个变量 a 和 b。请注意这一行


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

我们在这里对变量 a 和 b 进行按位与操作。

C++ 中的按位或运算符

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

下表演示了按位或运算符。设 a 和 b 是两个只具有二进制值(1 或 0)的操作数。

Bitwise OR Operator in C++ -Truth Table

让我们检查两个整数 15 和 36 的按位或操作

Bitwise OR Operator in C++ -Truth Table

按位或操作的示例


#include <iostream>
int main() {
    int a = 15, b = 36;
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "a | b = " << (a | b) << endl;
    return 0;
}

输出

a = 15
b = 36
a | b = 47

C++ 中的按位异或运算符

当且仅当其中一个操作数为 1 时,按位异或 ^ 运算符返回 1。但是,如果两个操作数都为零或都为一,则结果为零。
下表演示了按位异或运算符。设 a 和 b 是两个只具有二进制值(1 或 0)的操作数。

Bitwise XOR Operator in C++ -Truth Table

让我们检查两个整数 12 和 25 的按位异或操作

Bitwise XOR Operator in C++ -Truth Table

按位或操作的示例


#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。

C++ 中的按位一补码运算符

按位补码运算符是一种一元运算符(主要只作用于一个操作数)。它用 **~** 表示,它将二进制数字 1 转换为 0,将 0 转换为 1。

Bitwise ONE’S complement Operator in C++ - Truth Table

值得注意的是,任何整数 N 的按位补码等于 -(N + 1)。

让我们考虑一个整数 37。根据规则,37 的按位补码应该是 -(37 + 1) = -38。让我们检查我们是否得到了正确的答案。

Bitwise ONE’S complement Operator in C++ - Truth Table

在前面的示例中,**00100101** (37) 的按位补码是 **11011010**。当我们将这个结果转换为十进制时,我们将得到 218。

需要注意的是,我们不能简单地将结果转换为十进制并获得所需的输出。这是因为二进制结果 **11011010** 也等价于 -38。

要理解这一点,我们必须首先计算 -38 的二进制输出。为了计算负整数的二进制,我们使用 2 的补码。

2 的补码

  • -N 是数字 N 的 2 的补码。
  • 二进制算术中的 1 的补码将 0 转换为 1,将 1 转换为 0。
  • 如果我们向 1 的补码结果中添加 1,我们就会得到原始数字的 2 的补码。

例如:

Bitwise ONE’S complement Operator in C++ - Truth Table

在这种情况下,38 的 2 的补码(即 -38)是 11011010。在上一节中,我们计算了 37 的按位补码,该值与该数字等价。

因此,37 的按位补码是 -38。
 

按位补码的示例


#include <iostream>
int main() {
    int num1 = 25;
    int num2 = -160;
    cout << "~(" << num1 << ") = " << (~num1) << endl;
    cout << "~(" << num2 << ") = " << (~num2) << endl;

    return 0;
}

输出

~(25) = -26
~(-160) = 159

在前面的示例中,我们声明了两个整数变量 num1 和 num2,并分别用值 25 和 -160 初始化它们。

然后我们使用代码 **(~num1) 和 (~num2)** 分别计算并显示了它们的按位补码。

**25 = - (25 + 1) = -26** 的按位补码
即 **~35 = -36**

**-160 = - (-160 + 1) = - (-159) = 159** 的按位补码
即 **~(-160) = 159**

C++ 中的移位运算符

在 C++ 编程中,有两种移位运算符

  • 右移运算符 **>>**
  • 左移运算符 **<<**

C++ 中的右移运算符 >>

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

当我们向右移动一个数字时,我们丢弃最低有效位并用零替换它们。

Bitwise Shift Operator in C++ - Truth Table

我们有一个 4 位数字,如上图所示。当我们对其执行一位右移操作时,每个单独的位都向右移动一位。结果,最右边的位被丢弃,留下最左边的位为空。这个空位已经被 0 填充。

C++ 中的左移运算符 <<

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

Bitwise Shift Operator in C++ - Truth Table

这里显示一位左移

我们有一个 4 位数字,如上图所示。当我们对其执行 1 位左移操作时,每个单独的位都向左移动一位。

结果,最左边的位被丢弃,而最右边的位留空。这个空位已经被 0 填充。
 

移位运算符的示例


#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