位掩码(Bit Masking) 是一种使用位运算(AND、OR、XOR、NOT 等)来操作数据的技术,主要用于位级别的控制。位掩码(Bit Masking)是C语言中常用的技术,主要用于位操作,例如设置、清除、翻转或检查特定位。位掩码通常与按位运算符(&、|、^、~、<<、>>)一起使用。位掩码是 C 语言和嵌入式系统开发的核心技术,掌握它可以让代码更高效、更灵活。

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 = 00 ^ 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;
}

推荐文档