C语言位运算完全指南

底层编程

为什么需要位运算

位运算是 C 语言的精髓之一,直接操作内存中的二进制位,在底层编程、嵌入式系统、性能优化等场景中广泛应用。掌握位运算可以写出更高效、更节省内存的代码。

基本位运算符

C 语言提供 6 种基本位运算符:

按位与:a & b     // 两位都为 1 时结果为 1
按位或:a | b     // 至少有一位为 1 时结果为 1
按位异或:a ^ b   // 两位相异时结果为 1
按位取反:~a      // 所有位取反
左移:a << n    // 左移 n 位,低位补 0
右移:a >> n    // 右移 n 位,无符号高位补 0,有符号高位补符号位

位掩码技巧

位掩码是使用位运算处理单个位的常用技巧:

// 提取第 n 位(从 0 开始)
int get_bit(int x, int n) {
    return (x >> n) & 1;
}

// 设置第 n 位为 1
int set_bit(int x, int n) {
    return x | (1 << n);
}

// 清除第 n 位(设为 0)
int clear_bit(int x, int n) {
    return x & ~(1 << n);
}

// 切换第 n 位
int toggle_bit(int x, int n) {
    return x ^ (1 << n);
}

异或的妙用

异或运算有几个独特性质,可以用于一些巧妙操作:

// 性质 1:a ^ a = 0,a ^ 0 = a
// 性质 2:满足交换律和结合律
// 性质 3:不使用临时变量交换两个数
void swap(int *a, int *b) {
    *a = *a ^ *b;
    *b = *a ^ *b;  // 等价于 (*a^*b)^*b = *a
    *a = *a ^ *b;  // 等价于 (*a^*b)^*a = *b
}

// 找出数组中唯一出现一次的数,其他数都出现两次
int find_single(int *arr, int n) {
    int result = 0;
    for (int i = 0; i < n; i++) {
        result ^= arr[i];
    }
    return result;
}

位域

位域允许在结构体中直接定义位级别的成员:

struct Flags {
    unsigned int enable : 1;   // 占 1 位
    unsigned int mode : 2;     // 占 2 位
    unsigned int status : 4;  // 占 4 位
    unsigned int : 1;         // 保留位
};

struct Flags f;
f.enable = 1;
f.mode = 3;  // 最大值为 3(2 位能表示的最大值)

实际应用场景

位运算在实际开发中非常常见:

1. 权限控制:使用掩码判断用户权限标志位

2. 状态标志:用单个整数的不同位表示多种状态

3. 数据压缩:将多个小数据打包到一个字节中

4. 算法优化:快速乘除法(x << 1 相当于 x * 2)

5. 硬件交互:操作寄存器、嵌入式开发