1、位运算基础
位运算是处理二进制数据的基本操作。
运算 | 符号 | 示例 | 作用 |
---|---|---|---|
按位与(AND) | & | a & b | 清除不需要的位 |
按位或(OR) | ` | ` | `a |
按位异或(XOR) | ^ | a ^ b | 翻转位 |
按位取反(NOT) | ~ | ~a | 取反所有位 |
左移(Left Shift) | << | a << n | 左移 n 位(乘 2^n ) |
右移(Right Shift) | >> | a >> n | 右移 n 位(除 2^n ) |
2、位掩码简介
位掩码(Bit Masking) 是使用 掩码(Mask) 与数据进行按位操作,以提取、修改或检查特定位的值。
掩码通常是一个特定的二进制模式,用于操作数据中的特定位。
#include <stdio.h>
#define MASK 0x0F // 00001111,掩码定义
int main() {
int value = 0x3A; // 00111010
int result = value & MASK; // 只保留低 4 位
printf("Result: %X\n", result); // 输出: A (1010)
return 0;
}
3、常见的位掩码操作
1)检查某个位是否为 1
使用 AND (&
) 操作符,num & mask
只保留 mask
所在位,其它位清零。如果结果 ≠ 0
,则该位为 1
。
#include <stdio.h>
int main() {
int num = 0b10101100; // 172 (二进制: 10101100)
int mask = 0b00000100; // 4,对应二进制的第三位(从右往左,从0开始)
if (num & mask) {
printf("第 3 位是 1\n");
} else {
printf("第 3 位是 0\n");
}
return 0;
}
2)设置某个位为 1
使用 OR (|
) 操作符,OR 操作将 mask
指定位设置为 1
,其余位保持不变。
#include <stdio.h>
int main() {
int num = 0b10100000; // 初始值 160 (二进制: 10100000)
int mask = 0b00000100; // 掩码 4 (二进制: 00000100) - 对应设置第 3 位
num = num | mask; // 使用按位或运算符设置第 3 位
printf("新值: %d\n", num); // 164 (二进制: 10100100)
return 0;
}
3)清除某个位(设为 0)
使用 AND (&
) + NOT (~
),~mask
使 mask
指定位变为 0
,其他位保持 1
。AND 操作清除该位,其他位不变。
#include <stdio.h>
int main() {
int num = 0b10101100; // 172
int mask = 0b00000100; // 4,对应第三位
// 清除 num 的第 3 位
num = num & ~mask;
printf("新值: %d\n", num); // 输出 168 (10101000)
return 0;
}
4)翻转某个位
使用 XOR (^
),XOR 操作:1 ^ 1 = 0
,0 ^ 1 = 1
。只改变 mask
指定的位,其余位不变。
#include <stdio.h>
int main() {
int num = 0b10101100; // 172
int mask = 0b00000100; // 4,对应第三位
// 使用异或操作翻转 num 的第三位
num = num ^ mask;
// 输出翻转后的结果
printf("新值: %d\n", num); // 168 (10101000)
return 0;
}
4、其他应用
1)提取特定位
#include <stdio.h>
int main() {
int num = 0b11011010; // 218 (十进制)
int mask = 0b00001111; // 用于提取低 4 位
int result = num & mask; // 按位与运算,保留低 4 位
printf("低 4 位: %d\n", result); // 10 (0b1010)
printf("低 4 位 (二进制): 0b%b\n", result); // GCC 特殊扩展,非标准 C
return 0;
}
2)组合多个标志(Flags)
使用 OR (|
) 设置多个标志。使用|
组合多个权限标志。使用 &
检查是否具有某个权限。
#include <stdio.h>
#define FLAG_READ 0b0001 // 1
#define FLAG_WRITE 0b0010 // 2
#define FLAG_EXEC 0b0100 // 4
int main() {
int permissions = FLAG_READ | FLAG_WRITE; // 读 + 写权限
if (permissions & FLAG_READ) {
printf("有读权限\n");
}
if (permissions & FLAG_WRITE) {
printf("有写权限\n");
}
if (!(permissions & FLAG_EXEC)) {
printf("没有执行权限\n");
}
return 0;
}
3)使用位掩码压缩数据
存储 RGB 颜色(8 位 R、8 位 G、8 位 B),使用 <<
左移位存储颜色分量。使用 & 0xFF
提取颜色值。
#include <stdio.h>
int main() {
unsigned int color = 0;
// 设置 R、G、B 值
color |= (0x12 << 16); // 红色分量 (0x12)
color |= (0x34 << 8); // 绿色分量 (0x34)
color |= (0x56); // 蓝色分量 (0x56)
printf("颜色编码: 0x%X\n", color); // 颜色编码: 0x123456
// 解析 RGB 颜色
int red = (color >> 16) & 0xFF;
int green = (color >> 8) & 0xFF;
int blue = color & 0xFF;
printf("R: %X, G: %X, B: %X\n", red, green, blue); // R: 12, G: 34, B: 56
return 0;
}