C语言学习14-按位或(|)运算

按位或运算对两个数的二进制表示的每一位进行逻辑 操作:

  • 规则:两个对应位有一个为1时,结果就为1;只有两个都为0时结果才为0
  • 符号|
  • 特点:任何位与1相都会变成1,与0相保持原值

运算过程图示

#include <stdio.h>

void print_binary_5bit(int number) {
    for (int i = 4; i >= 0; i--) {
        printf("%d", (number >> i) & 1);
    }
}

int main() {
    unsigned int a = 0b00111;  // 十进制 7
    unsigned int b = 0b11100;  // 十进制 28
    
    printf("按位或运算示例:\n");
    printf("a = 7  (二进制: ");
    print_binary_5bit(a);
    printf(")\n");
    
    printf("b = 28 (二进制: ");
    print_binary_5bit(b);
    printf(")\n");
    
    printf("\n逐位运算过程:\n");
    printf("  ");
    print_binary_5bit(a);
    printf("\n| ");
    print_binary_5bit(b);
    printf("\n  -----\n  ");
    print_binary_5bit(a | b);
    printf("  (十进制 %d)\n", a | b);
    
    return 0;
}

运行结果:

按位或运算示例:
a = 7  (二进制: 00111)
b = 28 (二进制: 11100)

逐位运算过程:
  00111
| 11100
  -----
  11111  (十进制 31)

实用技巧详解

1. 设置特定位为1(最常用)

#include <stdio.h>

void print_binary_5bit(int number) {
    for (int i = 4; i >= 0; i--) {
        printf("%d", (number >> i) & 1);
    }
}

void set_last_bit_to_one(int number) {
    printf("\n将数字 %d 的最末位设置为1:\n", number);
    printf("原始数值: ");
    print_binary_5bit(number);
    printf(" (%d)\n", number);
    
    printf("掩码 1:   00001\n");
    printf("按位或运算:\n");
    printf("  ");
    print_binary_5bit(number);
    printf("\n| 00001\n");
    printf("  -----\n  ");
    print_binary_5bit(number | 1);
    printf(" (%d)\n", number | 1);
    
    printf("→ 最末位被强制设置为1\n");
}

void set_specific_bits() {
    unsigned int flags = 0b10100;  // 十进制 20
    unsigned int mask = 0b01011;   // 十进制 11
    
    printf("\n设置特定位示例:\n");
    printf("原始标志位: ");
    print_binary_5bit(flags);
    printf(" (%d)\n", flags);
    
    printf("设置掩码:   ");
    print_binary_5bit(mask);
    printf(" (要设置的位)\n");
    
    printf("按位或运算:\n");
    printf("  ");
    print_binary_5bit(flags);
    printf("\n| ");
    print_binary_5bit(mask);
    printf("\n  -----\n  ");
    print_binary_5bit(flags | mask);
    printf(" (%d)\n", flags | mask);
    
    printf("→ 掩码中为1的位都被设置为1\n");
}

int main() {
    set_last_bit_to_one(10);  // 1010 → 1011
    set_last_bit_to_one(15);  // 1111 → 1111 (不变)
    set_specific_bits();
    
    return 0;
}

运行结果:

将数字 10 的最末位设置为1:
原始数值: 01010 (10)
掩码 1:   00001
按位或运算:
  01010
| 00001
  -----
  01011 (11)
→ 最末位被强制设置为1

将数字 15 的最末位设置为1:
原始数值: 01111 (15)
掩码 1:   00001
按位或运算:
  01111
| 00001
  -----
  01111 (15)
→ 最末位被强制设置为1

设置特定位示例:
原始标志位: 10100 (20)
设置掩码:   01011 (要设置的位)
按位或运算:
  10100
| 01011
  -----
  11111 (31)
→ 掩码中为1的位都被设置为1

2. 权限授予系统

#include <stdio.h>

void print_binary_4bit(int number) {
    for (int i = 3; i >= 0; i--) {
        printf("%d", (number >> i) & 1);
    }
}

// 定义权限标志
#define READ_PERM   (1 << 0)  // 0001 - 读权限
#define WRITE_PERM  (1 << 1)  // 0010 - 写权限  
#define EXEC_PERM   (1 << 2)  // 0100 - 执行权限
#define ADMIN_PERM  (1 << 3)  // 1000 - 管理员权限

void grant_permissions(unsigned int current_perm, unsigned int new_perm, const char* user) {
    printf("\n为用户 %s 授予权限:\n", user);
    printf("当前权限: ");
    print_binary_4bit(current_perm);
    printf("\n授予权限: ");
    print_binary_4bit(new_perm);
    printf("\n按位或运算:\n");
    printf("  ");
    print_binary_4bit(current_perm);
    printf("\n| ");
    print_binary_4bit(new_perm);
    printf("\n  ----\n  ");
    
    unsigned int result = current_perm | new_perm;
    print_binary_4bit(result);
    printf(" (新权限)\n");
    
    // 解释权限含义
    printf("权限说明: ");
    if (result & READ_PERM) printf("读 ");
    if (result & WRITE_PERM) printf("写 ");
    if (result & EXEC_PERM) printf("执行 ");
    if (result & ADMIN_PERM) printf("管理");
    printf("\n");
}

int main() {
    printf("=== 权限管理系统 ===\n");
    
    // 初始用户只有读权限
    unsigned int user_perm = READ_PERM;
    
    grant_permissions(user_perm, WRITE_PERM, "张三");
    grant_permissions(user_perm | WRITE_PERM, EXEC_PERM, "张三");
    
    // 管理员一次性授予所有权限
    grant_permissions(0, READ_PERM | WRITE_PERM | EXEC_PERM, "管理员");
    
    return 0;
}

运行结果:

=== 权限管理系统 ===

为用户 张三 授予权限:
当前权限: 0001
授予权限: 0010
按位或运算:
  0001
| 0010
  ----
  0011 (新权限)
权限说明: 读 写 

为用户 张三 授予权限:
当前权限: 0011
授予权限: 0100
按位或运算:
  0011
| 0100
  ----
  0111 (新权限)
权限说明: 读 写 执行 

为用户 管理员 授予权限:
当前权限: 0000
授予权限: 0111
按位或运算:
  0000
| 0111
  ----
  0111 (新权限)
权限说明: 读 写 执行

3. 组合配置标志

#include <stdio.h>

void print_binary_8bit(int number) {
    for (int i = 7; i >= 0; i--) {
        printf("%d", (number >> i) & 1);
    }
}

// 定义配置选项
#define OPTION_A (1 << 0)  // 00000001
#define OPTION_B (1 << 1)  // 00000010
#define OPTION_C (1 << 2)  // 00000100
#define OPTION_D (1 << 3)  // 00001000
#define OPTION_E (1 << 4)  // 00010000

void build_configuration() {
    printf("=== 构建配置选项 ===\n");
    
    unsigned int config = 0;
    
    printf("初始配置: ");
    print_binary_8bit(config);
    printf("\n\n");
    
    // 逐步添加配置选项
    config |= OPTION_A;
    printf("添加选项A: ");
    print_binary_8bit(config);
    printf(" (A | 0)\n");
    
    config |= OPTION_C;
    printf("添加选项C: ");
    print_binary_8bit(config);
    printf(" (当前 | C)\n");
    
    config |= OPTION_E;
    printf("添加选项E: ");
    print_binary_8bit(config);
    printf(" (当前 | E)\n");
    
    // 一次性添加多个选项
    config |= (OPTION_B | OPTION_D);
    printf("添加B和D: ");
    print_binary_8bit(config);
    printf(" (当前 | (B | D))\n");
    
    printf("\n最终配置: ");
    print_binary_8bit(config);
    printf(" (所有选项都已设置)\n");
}

int main() {
    build_configuration();
    return 0;
}

运行结果:

=== 构建配置选项 ===

初始配置: 00000000

添加选项A: 00000001 (A | 0)
添加选项C: 00000101 (当前 | C)
添加选项E: 00010101 (当前 | E)
添加B和D: 00011111 (当前 | (B | D))

最终配置: 00011111 (所有选项都已设置)

重要注意事项

关于"最末位变成0"的说明

原文中提到"对这个数or 1之后再减一",这实际上不是推荐做法。正确的方法是使用按位与来清除位:

// ❌ 不推荐的做法
int number = 0b1010;  // 10
number = (number | 1) - 1;  // 变成 1001 (9)

// ✅ 推荐的做法
int number = 0b1010;  // 10
number = number & ~1;  // 变成 1000 (8) - 清除最末位

总结

按位或运算的核心用途:

  1. 设置特定位:将指定位强制设置为1

    • flags | mask 设置mask中所有为1的位
  2. 权限授予:添加权限而不影响其他权限

    • 用户权限 = 当前权限 | 新权限
  3. 配置组合:逐步构建配置选项

    • 配置 = 配置 | 新选项
  4. 合并标志:将多个标志合并为一个值

优势:

  • 非破坏性:只设置指定位,不影响其他位
  • 可组合:可以一次性设置多个位
  • 高效:单个操作完成多个设置

按位或运算是设置二进制特定位的首选工具!

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容