C++位运算符 #

一、位运算符概述 #

位运算符直接对整数的二进制位进行操作。

1.1 运算符列表 #

运算符 名称 示例 说明
& 位与 a & b 按位与
| 位或 a | b 按位或
^ 异或 a ^ b 按位异或
~ 取反 ~a 按位取反
<< 左移 a << n 左移n位
>> 右移 a >> n 右移n位

1.2 二进制基础 #

cpp
// 十进制转二进制
// 5  = 0000 0101
// 3  = 0000 0011
// 10 = 0000 1010
// 15 = 0000 1111

#include <iostream>
#include <bitset>

int main() {
    int x = 5;
    
    // 输出二进制(C++11)
    std::cout << std::bitset<8>(x) << std::endl;  // 00000101
    
    return 0;
}

二、位与运算符 & #

2.1 运算规则 #

text
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

2.2 基本示例 #

cpp
int a = 5;   // 0101
int b = 3;   // 0011
int c = a & b;  // 0001 = 1

// 详细过程:
//   0101 (5)
// & 0011 (3)
// ------
//   0001 (1)

2.3 常见应用 #

掩码操作 #

cpp
int value = 0b11010110;
int mask = 0b00001111;  // 低4位掩码

// 提取低4位
int low4 = value & mask;  // 0b00000110 = 6

// 检查特定位
int bit3 = value & 0b00001000;  // 检查第3位是否为1
if (bit3) {
    std::cout << "第3位是1" << std::endl;
}

判断奇偶 #

cpp
int n = 7;

// 使用位与判断奇偶
if (n & 1) {
    std::cout << "奇数" << std::endl;
} else {
    std::cout << "偶数" << std::endl;
}

清除特定位 #

cpp
int value = 0b11111111;

// 清除第3位(设为0)
value = value & ~0b00001000;  // 0b11110111

// 清除多个位
value = value & ~0b00001111;  // 清除低4位

三、位或运算符 | #

3.1 运算规则 #

text
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1

3.2 基本示例 #

cpp
int a = 5;   // 0101
int b = 3;   // 0011
int c = a | b;  // 0111 = 7

// 详细过程:
//   0101 (5)
// | 0011 (3)
// ------
//   0111 (7)

3.3 常见应用 #

设置特定位 #

cpp
int value = 0b10100000;

// 设置第3位为1
value = value | 0b00001000;  // 0b10101000

// 设置多个位
value = value | 0b00001111;  // 设置低4位

组合标志 #

cpp
// 权限标志
const int READ = 0b001;    // 1
const int WRITE = 0b010;   // 2
const int EXECUTE = 0b100; // 4

// 组合权限
int permission = READ | WRITE;  // 0b011 = 3

// 检查权限
if (permission & READ) {
    std::cout << "有读权限" << std::endl;
}
if (permission & WRITE) {
    std::cout << "有写权限" << std::endl;
}
if (permission & EXECUTE) {
    std::cout << "有执行权限" << std::endl;
}

四、异或运算符 ^ #

4.1 运算规则 #

text
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0

4.2 基本示例 #

cpp
int a = 5;   // 0101
int b = 3;   // 0011
int c = a ^ b;  // 0110 = 6

// 详细过程:
//   0101 (5)
// ^ 0011 (3)
// ------
//   0110 (6)

4.3 异或特性 #

cpp
// 1. 任何数与0异或,结果不变
int a = 5 ^ 0;  // 5

// 2. 任何数与自身异或,结果为0
int b = 5 ^ 5;  // 0

// 3. 异或满足交换律和结合律
int c = 5 ^ 3 ^ 5;  // 3

4.4 常见应用 #

交换两个数 #

cpp
int x = 5, y = 3;

// 使用异或交换(不需要临时变量)
x = x ^ y;  // x = 5 ^ 3 = 6
y = x ^ y;  // y = 6 ^ 3 = 5
x = x ^ y;  // x = 6 ^ 5 = 3

// 现在x = 3, y = 5

简单加密 #

cpp
char data = 'A';
char key = 0x55;

// 加密
char encrypted = data ^ key;

// 解密
char decrypted = encrypted ^ key;  // 'A'

找出只出现一次的数 #

cpp
int arr[] = {1, 2, 3, 2, 1};
int result = 0;

for (int n : arr) {
    result ^= n;
}
// result = 3(只出现一次的数)

五、取反运算符 ~ #

5.1 运算规则 #

text
~0 = 1
~1 = 0

5.2 基本示例 #

cpp
unsigned char a = 5;   // 0000 0101
unsigned char b = ~a;  // 1111 1010 = 250

// 有符号数
char c = 5;   // 0000 0101
char d = ~c;  // 1111 1010 = -6(补码)

5.3 常见应用 #

创建掩码 #

cpp
int value = 0b11111111;

// 清除低4位
int mask = ~0b00001111;  // 0b11110000
int result = value & mask;  // 0b11110000

六、左移运算符 << #

6.1 运算规则 #

左移n位相当于乘以2^n(对于无溢出的正数)。

cpp
int a = 5;      // 0000 0101
int b = a << 1; // 0000 1010 = 10
int c = a << 2; // 0001 0100 = 20
int d = a << 3; // 0010 1000 = 40

6.2 基本示例 #

cpp
int x = 1;

// 左移
x << 1;  // 2
x << 2;  // 4
x << 3;  // 8

6.3 常见应用 #

快速乘法 #

cpp
int n = 10;

// 乘以2
int doubled = n << 1;  // 20

// 乘以4
int quadrupled = n << 2;  // 40

// 乘以8
int octupled = n << 3;  // 80

创建掩码 #

cpp
// 创建第n位的掩码
int bit(int n) {
    return 1 << n;
}

// 使用
int mask = bit(3);  // 0b00001000

七、右移运算符 >> #

7.1 运算规则 #

右移n位相当于除以2^n(向下取整)。

cpp
int a = 20;     // 0001 0100
int b = a >> 1; // 0000 1010 = 10
int c = a >> 2; // 0000 0101 = 5
int d = a >> 3; // 0000 0010 = 2

7.2 算术右移 vs 逻辑右移 #

cpp
// 有符号数:算术右移(保留符号位)
int x = -8;     // 1111 1000(补码)
int y = x >> 1; // 1111 1100 = -4

// 无符号数:逻辑右移(补0)
unsigned int a = 0b10000000;
unsigned int b = a >> 1;  // 0b01000000

7.3 常见应用 #

快速除法 #

cpp
int n = 100;

// 除以2
int half = n >> 1;  // 50

// 除以4
int quarter = n >> 2;  // 25

// 除以8
int eighth = n >> 3;  // 12

提取位 #

cpp
int value = 0b11010110;

// 提取第n位
bool getBit(int value, int n) {
    return (value >> n) & 1;
}

// 使用
bool bit2 = getBit(value, 2);  // true (第2位是1)

八、位运算综合应用 #

8.1 位操作函数 #

cpp
// 设置第n位为1
int setBit(int num, int n) {
    return num | (1 << n);
}

// 清除第n位(设为0)
int clearBit(int num, int n) {
    return num & ~(1 << n);
}

// 切换第n位
int toggleBit(int num, int n) {
    return num ^ (1 << n);
}

// 检查第n位是否为1
bool isBitSet(int num, int n) {
    return (num & (1 << n)) != 0;
}

// 修改第n位为指定值
int changeBit(int num, int n, bool value) {
    if (value) {
        return setBit(num, n);
    } else {
        return clearBit(num, n);
    }
}

8.2 统计二进制中1的个数 #

cpp
int countOnes(int n) {
    int count = 0;
    while (n) {
        count += n & 1;
        n >>= 1;
    }
    return count;
}

// 更高效的方法
int countOnes2(int n) {
    int count = 0;
    while (n) {
        n &= n - 1;  // 清除最低位的1
        count++;
    }
    return count;
}

// C++20:使用std::popcount
#include <bit>
int count = std::popcount(n);

8.3 判断是否是2的幂 #

cpp
bool isPowerOfTwo(int n) {
    return n > 0 && (n & (n - 1)) == 0;
}

// 示例
isPowerOfTwo(8);   // true (1000)
isPowerOfTwo(6);   // false (0110)

8.4 颜色操作 #

cpp
// RGB颜色打包
int packColor(unsigned char r, unsigned char g, unsigned char b) {
    return (r << 16) | (g << 8) | b;
}

// 解包
unsigned char getRed(int color) { return (color >> 16) & 0xFF; }
unsigned char getGreen(int color) { return (color >> 8) & 0xFF; }
unsigned char getBlue(int color) { return color & 0xFF; }

// 使用
int color = packColor(255, 128, 64);  // 0xFF8040

九、位运算与逻辑运算的区别 #

cpp
// 位运算:对每一位进行操作
int a = 5 & 3;   // 1
int b = 5 | 3;   // 7

// 逻辑运算:返回布尔值,短路求值
bool c = 5 && 3;  // true
bool d = 5 || 0;  // true

// 常见错误
if (x & 1) { }   // 检查奇偶,正确
if (x && 1) { }  // 检查x非零,不是奇偶检查!

十、最佳实践 #

10.1 使用unsigned类型 #

cpp
// 推荐:使用unsigned避免符号位问题
unsigned int x = 0xFFFFFFFF;
unsigned int y = x >> 1;  // 0x7FFFFFFF

// 有符号数右移可能有问题
int a = -1;
int b = a >> 1;  // 结果取决于编译器

10.2 使用括号 #

cpp
// 位运算优先级较低
int result = a & b == c;  // 错误!等价于 a & (b == c)
int result = (a & b) == c;  // 正确

10.3 使用有意义的常量 #

cpp
// 不推荐
int flags = 0b00001111;

// 推荐
const int LOW_NIBBLE_MASK = 0x0F;
int flags = LOW_NIBBLE_MASK;

十一、总结 #

位运算符一览 #

运算符 名称 示例 结果
& 位与 5 & 3 1
| 位或 5 | 3 7
^ 异或 5 ^ 3 6
~ 取反 ~5 -6
<< 左移 5 << 1 10
>> 右移 5 >> 1 2

常见应用 #

应用 方法
判断奇偶 n & 1
乘以2 n << 1
除以2 n >> 1
设置位 n | (1 << i)
清除位 n & ~(1 << i)
切换位 n ^ (1 << i)
检查位 n & (1 << i)

下一步,让我们学习赋值运算符!

最后更新:2026-03-26