知识点#
11.1 位的概念和位运算符简介#
- @ 位运算基础图
- ![[白板/P32 位运算基础.canvas|P32 位运算基础]]
11.1.1 位的概念#
[!tip] 位的基本概念
- 1 字节 = 8 个二进制位
- 最左边的位称为==最高位==,最右边的位称为==最低位==
- 每个二进制位的值是
0或1unsigned int占 4 字节 = 32 个二进制位,最大值4294967295
| 类型 | 字节数 | 二进制位数 |
|---|---|---|
char | 1 | 8 |
int | 4 | 32 |
unsigned int | 4 | 32 |
11.1.2 位运算符简介#
| 位运算符 | 含义 | 运算类型 |
|---|---|---|
& | 按位与 | 二目 |
| | 按位或 | 二目 |
^ | 按位异或 | 二目 |
~ | 取反 | 单目 |
<< | 左移 | 二目 |
>> | 右移 | 二目 |
1. 按位与运算符 &#
[!tip] 按位与
- 两个相应位都为
1,结果为1,否则为0- 公式:
0&0=0; 0&1=0; 1&0=0; 1&1=1
unsigned int tempvalue = 38 & 22; // 6
// 计算过程(二进制):
// 100110 (38)
// 010110 (22)
// ------ (&)
// 000110 (6)
2. 按位或运算符 |#
[!tip] 按位或
- 两个相应位有一个为
1,结果为1,否则为0- 公式:
0|0=0; 0|1=1; 1|0=1; 1|1=1
unsigned int tempvalue = 38 | 22; // 54
// 计算过程(二进制):
// 100110 (38)
// 010110 (22)
// ------ (|)
// 110110 (54)
3. 按位异或运算符 ^#
[!tip] 按位异或
- 两个相应位相同为
0,不同为1- ==都一样出 0,不一样出 1==
- 公式:
0^0=0; 0^1=1; 1^0=1; 1^1=0
unsigned int tempvalue = 38 ^ 22; // 49
// 计算过程(二进制):
// 100110 (38)
// 010110 (22)
// ------ (^)
// 110000 (49)
- ! 与
1异或→翻转,与0异或→保持不变
// 低4位翻转,高4位保持不变
// 01111010
// 00001111
// -------- (^)
// 01110101
4. 取反运算符 ~#
[!tip] 取反
- 单目运算符,
0变1,1变0
unsigned int tempvalue = ~38; // 4294967257
// 计算过程:
// 00000000,00000000,00000000,00100110 (38)
// ------------------------------------ (~)
// 11111111,11111111,11111111,11011001 (4294967257)
5. 左移运算符 <<#
[!tip] 左移
- 二进制位左移若干位,右侧补
0- ==每左移一位相当于乘以 2==
unsigned int tempvalue = 15 << 1; // 30
// 01111 → 11110
unsigned int tempvalue = 15 << 2; // 60
// 001111 → 111100
6. 右移运算符 >>#
[!tip] 右移
- 二进制位右移若干位,超出的位被舍弃,左侧补
0- ==每右移一位相当于除以 2==
unsigned int tempvalue = 15 >> 1; // 7
// 1111 → 0111
unsigned int tempvalue = 15 >> 2; // 3
// 1111 → 0011
复合赋值运算符#
| 复合运算符 | 等价写法 |
|---|---|
a &= b | a = a & b |
a |= b | a = a | b |
a ^= b | a = a ^ b |
a <<= b | a = a << b |
a >>= b | a = a >> b |
int a = 35;
int b = 22;
a &= b; // a = a & b = 2
// 100011 (35)
// 010110 (22)
// ------ (&)
// 000010 (2)
11.2 位运算的具体应用#
- @ 位运算应用图
- ![[白板/P33 位运算应用.canvas|P33 位运算应用]]
实际应用: 每日任务标记#
[!tip] 位运算实际用途
- 用一个
unsigned int变量记录多达 32 种状态- 每个二进制位代表一个任务:
0= 未完成,1= 已完成- 通过按位与判断任务是否完成
- 通过按位或标记任务完成
核心宏定义#
#define BIT(n) (1 << (n)) // 实用价值极高
// BIT(0) = 1, BIT(1) = 2, BIT(2) = 4, BIT(3) = 8
// BIT(4) = 16, BIT(5) = 32, BIT(6) = 64, BIT(7) = 128
// BIT(8) = 256, BIT(9) = 512
BIT(n) | 十进制 | 二进制 | 左移位数 |
|---|---|---|---|
BIT(0) | 1 | 1 | 左移 0 位 |
BIT(1) | 2 | 10 | 左移 1 位 |
BIT(2) | 4 | 100 | 左移 2 位 |
BIT(3) | 8 | 1000 | 左移 3 位 |
BIT(4) | 16 | 10000 | 左移 4 位 |
BIT(5) | 32 | 100000 | 左移 5 位 |
BIT(6) | 64 | 1000000 | 左移 6 位 |
BIT(7) | 128 | 10000000 | 左移 7 位 |
完整实现代码#
// 定义10个任务的枚举
enum ETask {
ETask1 = BIT(0), // 1 = 1
ETask2 = BIT(1), // 2 = 10
ETask3 = BIT(2), // 4 = 100
ETask4 = BIT(3), // 8 = 1000
ETask5 = BIT(4), // 16 = 10000
ETask6 = BIT(5), // 32 = 100000
ETask7 = BIT(6), // 64 = 1000000
ETask8 = BIT(7), // 128 = 10000000
ETask9 = BIT(8), // 256 = 100000000
ETask10 = BIT(9) // 512 = 1000000000
};
unsigned int task = 0; // 初始化为0,所有任务未完成
// 判断任务7是否完成
if (task & ETask7) { // 按位与,不为0表示做过
printf("任务7已经做过了\n");
} else {
printf("任务7还没做过,现在做任务7\n");
// 标记任务7完成(按位或)
task = task | ETask7; // 将第7位标记为1
}
// 再次判断
if (task & ETask7) {
printf("任务7已经做过了,可以保存到数据库\n");
}
位运算操作总结#
| 操作 | 运算符 | 说明 |
|---|---|---|
判断某位是否为 1 | task & BIT(n) | 结果不为 0 表示该位为 1 |
将某位置为 1 | task |= BIT(n) | 按位或,标记任务完成 |
将某位置为 0 | task &= ~BIT(n) | 按位与取反,清除标记 |
| 翻转某位 | task ^= BIT(n) | 按位异或,0↔1 切换 |
- ! 一个
unsigned int变量可记录 32 种状态,节省大量存储空间

