C++(9):位运算符进阶版
1. 变量定义
变量 A = 45(二进制 0010 1101
),B = 25(二进制 0001 1001
):
int A = 45; // 二进制: 0010 1101 (十进制45)
int B = 25; // 二进制: 0001 1001 (十进制25)
2. 位运算符表
运算符 | 名称 | 规则 | 实例 | 结果(二进制) | 十进制结果 | ||
---|---|---|---|---|---|---|---|
& | 按位与 | 同1为1,否则为0 | A & B | 0000 1001 | 9 | ||
| | 按位或 | 有1为1,全0为0 | A|B | 0011 1101 | 61 | ||
^ | 按位异或 | 不同为1,相同为0 | A ^ B | 0011 0100 | 52 | ||
~ | 按位取反 | 0变1,1变0(补码形式) | ~A | 1101 0010 (8位简写) | -46 | ||
<< | 左移 | 左移指定位,右侧补0 | A << 2 | 1011 0100 | 180 | ||
>> | 右移 | 右移指定位,正数左侧补0,负数补1 | B >> 2 | 0000 0110 | 6 |
3. 代码实例与验证
#include <iostream>
#include <bitset> int main() {int A = 45; // 0010 1101int B = 25; // 0001 1001// 按位与 &std::cout << "A & B = " << (A & B) << " (二进制: " << std::bitset<8>(A & B) << ")\n";// 输出: A & B = 9 (二进制: 00001001)// 按位或 |std::cout << "A | B = " << (A | B) << " (二进制: " << std::bitset<8>(A | B) << ")\n";// 输出: A | B = 61 (二进制: 00111101)// 按位异或 ^std::cout << "A ^ B = " << (A ^ B) << " (二进制: " << std::bitset<8>(A ^ B) << ")\n";// 输出: A ^ B = 52 (二进制: 00110100)// 按位取反 ~(8位简写,实际为32位)std::cout << "~A = " << (~A) << " (二进制: " << std::bitset<8>(~A) << ")\n";// 输出: ~A = -46 (二进制: 11010010)// 左移 <<std::cout << "A << 2 = " << (A << 2) << " (二进制: " << std::bitset<8>(A << 2) << ")\n";// 输出: A << 2 = 180 (二进制: 10110100)// 右移 >>std::cout << "B >> 2 = " << (B >> 2) << " (二进制: " << std::bitset<8>(B >> 2) << ")\n";// 输出: B >> 2 = 6 (二进制: 00000110)return 0;
}
4. 关键规则说明
(1) 按位与 "&"
规则:仅当两位均为 1
时结果为 1
。
示例计算:
0010 1101 (A=45)& 0001 1001 (B = 25) = 0000 1001 (十进制9)
(2) 按位或 "|"
规则:任一位为 `1` 则结果为 `1`。 - **示例计算**:
示例计算:
0010 1101 (A=45) | 0001 1001 (B=25) = 0011 1101 (十进制61)
(3) 按位异或 "^"
规则:两位不同时结果为 `1`。 -
示例计算:
0010 1101 (A=45) ^ 0001 1001 (B=25) = 0011 0100 (十进制52)
(4) 按位取反 "~"
规则:按位取反后结果为补码形式。
示例计算:
A = 0010 1101
~A = 1101 0010 → 十进制为 -46(补码转换:符号位为1,数值位取反加1)
(5) 位移运算符
左移 `<<`:
左移 n
位 = 乘以 2^n(无溢出时),左侧溢出位丢弃,右侧补0。
45 << 2 = 45 * 4 = 180//0010 1101 → 左移2位 → 1011 0100,后面自动补0
右移 `>>`:
右移 n
位 = 除以 2^n,正数左侧补0,负数补1。
25 >> 2 = 25 / 4 = 6//0001 1001 → 右移2位 → 0000 0110
5. 实际应用场景
场景 1:标志位组合
const int FLAG_A = 1 << 0; // 0001
const int FLAG_B = 1 << 1; // 0010
int flags = FLAG_A | FLAG_B; // 0011(同时启用两个标志)
场景 2:快速乘除
int num = 30;
int doubled = num << 1; // 60(等价于 30*2)
int quarter = num >> 2; // 7(等价于 30/4,向下取整)
场景 3:权限校验
const int READ = 1; // 0001
const int WRITE = 2; // 0010
int userPermission = READ;if ((userPermission & WRITE) != 0) {std::cout << "用户有写权限";
} else {std::cout << "无写权限"; // 输出此结果
}
6. 注意事项
-
位数限制:
std::bitset<8>
仅显示8位,实际int
类型为32或64位,负数需用补码完整表示。 -
符号位影响:
右移负数时结果依赖编译器实现(算术右移或逻辑右移)。 -
溢出风险:
左移可能导致溢出(如A << 2
若为8位则结果为10110100
,但实际int
类型会保留高位)。