C++中的‘位’操作

目录

摘要

基本位操作

[1. 按位与(AND)`&`:](#1. 按位与(AND)&:)

[2. 按位或(OR)`|`:](#2. 按位或(OR)|:)

[3. 按位异或(XOR)`^`:](#3. 按位异或(XOR)^:)

[4. 按位取反(NOT)`~`:](#4. 按位取反(NOT)~:)

[5. 左移(Left Shift)`<<`:](#5. 左移(Left Shift)<<:)

高级用法

[1. 快速乘除以2的幂:](#1. 快速乘除以2的幂:)

[2. 交换两个数(不使用临时变量):](#2. 交换两个数(不使用临时变量):)

[3. 检测奇偶性:](#3. 检测奇偶性:)

[4. 清除最低位的1:](#4. 清除最低位的1:)

[5. 获取最低位的1:](#5. 获取最低位的1:)

[6. 统计二进制中1的个数:](#6. 统计二进制中1的个数:)

[7. 快速判断是否是2的幂:](#7. 快速判断是否是2的幂:)

与宏定义结合

[1. 设置某一位:](#1. 设置某一位:)

[2. 清除某一位:](#2. 清除某一位:)

[3. 切换某一位:](#3. 切换某一位:)

[4. 检查某一位是否为1:](#4. 检查某一位是否为1:)

[5. 计算二进制中1的个数:](#5. 计算二进制中1的个数:)

总结


摘要

在C++中,位操作可以通过位与(AND )、位或(OR )、位异或(XOR )、位取反(NOT )、左移(Left Shift )和右移(Right Shift)等操作来实现。如果结合宏定义来使用,可以使位操作更加简洁。

基本位操作

1. 按位与(AND )`&`:

每个位进行与运算,只有对应位都为1时,结果位才为1。

cpp 复制代码
int a = 5;  // 0101
int b = 3;  // 0011
int result = a & b;  // 0001 -> 1

2. 按位或(OR )`|`:

每个位进行或运算,只要对应位有一个为1,结果位就为1。

cpp 复制代码
int a = 5;  // 0101
int b = 3;  // 0011
int result = a | b;  // 0111 -> 7

3. 按位异或(XOR )`^`:

cpp 复制代码
int a = 5;  // 0101
int b = 3;  // 0011
int result = a ^ b;  // 0110 -> 6

每个位进行异或运算,对应位相同为0,不同为1。

4. 按位取反(NOT )`~`:

将每个位取反,0变1,1变0。

cpp 复制代码
int a = 5;  // 0101
int result = ~a;  // 1010 -> -6(在补码表示中)

5. 左移(Left Shift)`<<`:

将二进制数的所有位向左移动指定的位数,右边补0。

cpp 复制代码
int a = 5;  // 0101
int result = a << 1;  // 1010 -> 10
  1. 右移(Right Shift )`>>`:

将二进制数的所有位向右移动指定的位数,左边补符号位(算术右移)或0(逻辑右移)。

cpp 复制代码
int a = 5;  // 0101
int result = a >> 1;  // 0010 -> 2

高级用法

1. 快速乘除以2的幂:

左移操作相当于乘以2的幂,右移操作相当于除以2的幂。

cpp 复制代码
int a = 5;
int result = a << 3;  // 相当于 a * 8 -> 40
result = a >> 2;  // 相当于 a / 4 -> 1

2. 交换两个数(不使用临时变量):

可以使用异或操作来交换两个数。

cpp 复制代码
int a = 5;
int b = 3;
a = a ^ b;
b = a ^ b;
a = a ^ b;
// 现在 a = 3, b = 5

3. 检测奇偶性:

使用按位与操作来检测一个数是奇数还是偶数。

cpp 复制代码
int a = 5;
bool isOdd = a & 1;  // 如果 a 的最后一位是1,则是奇数

4. 清除最低位的1:

通过 `x & (x - 1)` 可以清除最低位的1。

cpp 复制代码
int a = 12;  // 1100
int result = a & (a - 1);  // 1000 -> 8

5. 获取最低位的1:

使用 `x & -x` 可以获取最低位的1。

cpp 复制代码
int a = 12;  // 1100
int result = a & -a;  // 0100 -> 4

6. 统计二进制中1的个数:

可以通过反复清除最低位的1来统计一个整数中1的个数。

cpp 复制代码
int countOnes(int x) {
    int count = 0;
    while (x) {
        x = x & (x - 1);
        count++;
    }
    return count;
}

7. 快速判断是否是2的幂:

一个数如果是2的幂,则它的二进制表示中只有一个1。

cpp 复制代码
bool isPowerOfTwo(int x) {
    return x > 0 && (x & (x - 1)) == 0;
}

与宏定义结合

通过将位操作与宏定义结合,可以提高代码的可读性和可维护性,同时保留位操作的高效性。

1. 设置某一位:

cpp 复制代码
#define SET_BIT(x, pos) ((x) | (1 << (pos)))
int x = 5;  // 0101
x = SET_BIT(x, 1);  // 设置第1位 -> 0111 -> 7

2. 清除某一位:

cpp 复制代码
#define CLEAR_BIT(x, pos) ((x) & ~(1 << (pos)))
int x = 7;  // 0111
x = CLEAR_BIT(x, 1);  // 清除第1位 -> 0101 -> 5

3. 切换某一位:

cpp 复制代码
#define TOGGLE_BIT(x, pos) ((x) ^ (1 << (pos)))
int x = 5;  // 0101
x = TOGGLE_BIT(x, 1);  // 切换第1位 -> 0111 -> 7
x = TOGGLE_BIT(x, 1);  // 再次切换第1位 -> 0101 -> 5

4. 检查某一位是否为1:

cpp 复制代码
#define CHECK_BIT(x, pos) ((x) & (1 << (pos)))
int x = 5;  // 0101
bool isSet = CHECK_BIT(x, 2);  // 检查第2位 -> 0100 -> true

5. 计算二进制中1的个数:

cpp 复制代码
#define COUNT_ONES(x) ({ \
    int count = 0; \
    int n = (x); \
    while (n) { \
        n &= (n - 1); \
        count++; \
    } \
    count; \
})
int x = 15;  // 1111
int onesCount = COUNT_ONES(x);  // 4

总结

在C++中使用位操作一定需要注意自己的需求是什么,对位操作一定要仔细,否则很容易出现问题。同时,通过位操作可以优化代码,并且如果有涉及到一些算法的地方,也可以用位操作来优化算法,提高整体性能。

相关推荐
※DX3906※8 分钟前
cpp实战项目—string类的模拟实现
开发语言·c++
努力学习java的哈吉米大王38 分钟前
数据结构-队列
数据结构
Joyner201844 分钟前
python-leetcode-从中序与后序遍历序列构造二叉树
算法·leetcode·职场和发展
因兹菜1 小时前
[LeetCode]day9 203.移除链表元素
算法·leetcode·链表
LNsupermali1 小时前
力扣257. 二叉树的所有路径(遍历思想解决)
算法·leetcode·职场和发展
雾月551 小时前
LeetCode LCR180文件组合
算法·leetcode·职场和发展
萌の鱼1 小时前
leetcode 2080. 区间内查询数字的频率
数据结构·c++·算法·leetcode
Tisfy1 小时前
LeetCode 0541.反转字符串 II:模拟
算法·leetcode·字符串·题解
xianwu5432 小时前
反向代理模块jmh
开发语言·网络·数据库·c++·mysql
CM莫问2 小时前
什么是门控循环单元?
人工智能·pytorch·python·rnn·深度学习·算法·gru