- C++
C++位运算符教程 通俗易懂 0基础 详细
- 2025-3-13 21:47:15 @
1. 什么是位运算符
在 C++ 里,位运算符主要是对整数类型(像 int
、char
等)的数据按二进制位进行操作。位运算能直接操作数据的二进制位,在某些场景下可显著提升程序的执行效率,还能用于实现特定的功能,例如数据加密、压缩以及底层硬件控制等。
2. 常见的位运算符
2.1 按位与运算符(&
)
- 运算规则:对两个操作数的对应二进制位进行与运算,只有当两个对应位都为 1 时,结果位才为 1,否则为 0。
- 示例代码:
#include <iostream>
int main() {
int a = 5; // 二进制表示: 0101
int b = 3; // 二进制表示: 0011
int result = a & b; // 按位与运算
std::cout << "5 & 3 的结果是: " << result << std::endl;
return 0;
}
- 代码解释:
- 5 的二进制是 0101,3 的二进制是 0011。
- 按位与运算时,从右到左逐位比较:
- 第 1 位:1 和 1 相与得 1。
- 第 2 位:0 和 1 相与得 0。
- 第 3 位:1 和 0 相与得 0。
- 第 4 位:0 和 0 相与得 0。
- 所以结果是 0001,即十进制的 1。
2.2 按位或运算符(|
)
- 运算规则:对两个操作数的对应二进制位进行或运算,只要两个对应位中有一个为 1,结果位就为 1,只有当两个对应位都为 0 时,结果位才为 0。
- 示例代码:
#include <iostream>
int main() {
int a = 5; // 二进制表示: 0101
int b = 3; // 二进制表示: 0011
int result = a | b; // 按位或运算
std::cout << "5 | 3 的结果是: " << result << std::endl;
return 0;
}
- 代码解释:
- 5 的二进制是 0101,3 的二进制是 0011。
- 按位或运算时,从右到左逐位比较:
- 第 1 位:1 和 1 相或得 1。
- 第 2 位:0 和 1 相或得 1。
- 第 3 位:1 和 0 相或得 1。
- 第 4 位:0 和 0 相或得 0。
- 所以结果是 0111,即十进制的 7。
2.3 按位异或运算符(^
)
- 运算规则:对两个操作数的对应二进制位进行异或运算,当两个对应位不同时,结果位为 1,相同时结果位为 0。
- 示例代码:
#include <iostream>
int main() {
int a = 5; // 二进制表示: 0101
int b = 3; // 二进制表示: 0011
int result = a ^ b; // 按位异或运算
std::cout << "5 ^ 3 的结果是: " << result << std::endl;
return 0;
}
- 代码解释:
- 5 的二进制是 0101,3 的二进制是 0011。
- 按位异或运算时,从右到左逐位比较:
- 第 1 位:1 和 1 异或得 0。
- 第 2 位:0 和 1 异或得 1。
- 第 3 位:1 和 0 异或得 1。
- 第 4 位:0 和 0 异或得 0。
- 所以结果是 0110,即十进制的 6。
2.4 按位取反运算符(~
)
- 运算规则:对操作数的每个二进制位取反,即 1 变为 0,0 变为 1。
- 示例代码:
#include <iostream>
int main() {
int a = 5; // 二进制表示: 0101
int result = ~a; // 按位取反运算
std::cout << "~5 的结果是: " << result << std::endl;
return 0;
}
- 代码解释:
- 5 的二进制是 0101。
- 按位取反后得到 1010。
- 在计算机中,整数通常以补码形式存储,这里得到的 1010 是补码形式。要得到其十进制值,先减 1 得到反码 1001,再取反得到原码 1110,即十进制的 -6。
2.5 左移运算符(<<
)
- 运算规则:将操作数的二进制位向左移动指定的位数,右边空出的位用 0 填充。左移一位相当于将该数乘以 2。
- 示例代码:
#include <iostream>
int main() {
int a = 5; // 二进制表示: 0101
int result = a << 2; // 左移 2 位
std::cout << "5 << 2 的结果是: " << result << std::endl;
return 0;
}
- 代码解释:
- 5 的二进制是 0101。
- 左移 2 位后得到 010100,即十进制的 20。
2.6 右移运算符(>>
)
- 运算规则:将操作数的二进制位向右移动指定的位数。对于无符号数,左边空出的位用 0 填充;对于有符号数,左边空出的位用符号位填充(正数用 0 填充,负数用 1 填充)。右移一位相当于将该数除以 2。
- 示例代码:
#include <iostream>
int main() {
int a = 8; // 二进制表示: 1000
int result = a >> 2; // 右移 2 位
std::cout << "8 >> 2 的结果是: " << result << std::endl;
return 0;
}
- 代码解释:
- 8 的二进制是 1000。
- 右移 2 位后得到 0010,即十进制的 2。
3. 位运算符的常见应用
3.1 判断奇偶性
可以使用按位与运算符 &
来判断一个数是奇数还是偶数。如果一个数的二进制表示的最低位是 1,则该数为奇数;如果最低位是 0,则该数为偶数。可以将该数与 1 进行按位与运算,如果结果为 1,则是奇数;结果为 0,则是偶数。
#include <iostream>
void checkEvenOdd(int num) {
if (num & 1) {
std::cout << num << " 是奇数。" << std::endl;
} else {
std::cout << num << " 是偶数。" << std::endl;
}
}
int main() {
int num = 7;
checkEvenOdd(num);
return 0;
}
3.2 交换两个数的值
可以使用按位异或运算符 ^
来交换两个数的值,而无需使用额外的临时变量。
#include <iostream>
void swap(int& a, int& b) {
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
int main() {
int x = 5;
int y = 3;
std::cout << "交换前: x = " << x << ", y = " << y << std::endl;
swap(x, y);
std::cout << "交换后: x = " << x << ", y = " << y << std::endl;
return 0;
}
4. 总结
位运算符能直接操作数据的二进制位,在某些场景下可提高程序效率。在使用位运算符时,要清楚操作数的二进制表示以及运算符的运算规则。同时,要留意不同类型(有符号数和无符号数)在右移操作时的差异。通过不断练习,你能更熟练地运用位运算符解决实际问题。
1 条评论
-
admin SU @ 2025-3-13 21:48:48已修改
要更好地理解位运算符的优先级,可以从了解优先级顺序、借助表达式示例、结合代码实践以及与逻辑运算符对比等方面入手,下面为你详细介绍:
1. 牢记位运算符优先级顺序
在C++里,位运算符的优先级高低有所不同,你需要记住常见位运算符的优先级顺序。一般而言,按位取反运算符(
~
)优先级最高,接着是左移(<<
)和右移(>>
)运算符,然后是按位与(&
)运算符,再之后是按位异或(^
)运算符,最后是按位或(|
)运算符。你可以参考下面这个完整的运算符优先级表格,位运算符相关部分已经加粗展示:
2. 借助表达式示例理解
可以通过一些具体的表达式示例来深入理解优先级。例如对于表达式
3 & 5 << 2
,根据优先级,先进行左移操作5 << 2
,5 的二进制是 0101,左移 2 位后得到 010100 即 20,然后再进行按位与操作3 & 20
,3 的二进制是 0011,20 的二进制是 010100,按位与结果为 0,所以整个表达式结果是 0。3. 结合代码实践体会
自己编写一些包含多种位运算符的代码,然后运行并观察结果,通过这种方式能更直观地感受优先级的影响。以下是一个示例代码:
#include <iostream> int main() { int a = 3; int b = 5; int c = 2; // 按照优先级计算 int result = a & b << c; std::cout << "表达式 a & b << c 的结果是: " << result << std::endl; return 0; }
在这个代码中,你可以修改变量的值和运算符,运行程序观察不同情况下的计算结果,从而加深对优先级的理解。
4. 与逻辑运算符对比
把位运算符和逻辑运算符(如
&&
、||
)放在一起对比,了解它们之间的优先级关系。逻辑运算符的优先级通常低于位运算符,例如在表达式3 & 5 || 2 << 1
中,会先计算3 & 5
和2 << 1
,再进行逻辑或运算。5. 使用括号明确运算顺序
当表达式较为复杂,难以确定运算顺序时,可使用括号来明确优先级。例如
(3 & 5) << 2
就明确了先进行按位与操作,再进行左移操作。这样不仅能保证计算结果符合预期,还能提高代码的可读性。6. 分析错误案例
尝试编写一些故意违背优先级规则的代码,运行后观察出现的错误结果,然后分析原因,这样能更深刻地理解优先级的重要性。例如,如果错误地认为按位与运算符优先级高于左移运算符,写出
3 & (5 << 2)
以外的错误表达式,运行后结果会和预期不符,此时分析错误就能强化对优先级的认识。
- 1