C語(yǔ)言學(xué)習(xí)14-按位或(|)運(yùn)算

按位或運(yùn)算對(duì)兩個(gè)數(shù)的二進(jìn)制表示的每一位進(jìn)行邏輯 操作:

  • 規(guī)則:兩個(gè)對(duì)應(yīng)位有一個(gè)為1時(shí),結(jié)果就為1;只有兩個(gè)都為0時(shí)結(jié)果才為0
  • 符號(hào)|
  • 特點(diǎn):任何位與1相都會(huì)變成1,與0相保持原值

運(yùn)算過程圖示

#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;  // 十進(jìn)制 7
    unsigned int b = 0b11100;  // 十進(jìn)制 28
    
    printf("按位或運(yùn)算示例:\n");
    printf("a = 7  (二進(jìn)制: ");
    print_binary_5bit(a);
    printf(")\n");
    
    printf("b = 28 (二進(jìn)制: ");
    print_binary_5bit(b);
    printf(")\n");
    
    printf("\n逐位運(yùn)算過程:\n");
    printf("  ");
    print_binary_5bit(a);
    printf("\n| ");
    print_binary_5bit(b);
    printf("\n  -----\n  ");
    print_binary_5bit(a | b);
    printf("  (十進(jìn)制 %d)\n", a | b);
    
    return 0;
}

運(yùn)行結(jié)果:

按位或運(yùn)算示例:
a = 7  (二進(jìn)制: 00111)
b = 28 (二進(jìn)制: 11100)

逐位運(yùn)算過程:
  00111
| 11100
  -----
  11111  (十進(jìn)制 31)

實(shí)用技巧詳解

1. 設(shè)置特定位為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將數(shù)字 %d 的最末位設(shè)置為1:\n", number);
    printf("原始數(shù)值: ");
    print_binary_5bit(number);
    printf(" (%d)\n", number);
    
    printf("掩碼 1:   00001\n");
    printf("按位或運(yùn)算:\n");
    printf("  ");
    print_binary_5bit(number);
    printf("\n| 00001\n");
    printf("  -----\n  ");
    print_binary_5bit(number | 1);
    printf(" (%d)\n", number | 1);
    
    printf("→ 最末位被強(qiáng)制設(shè)置為1\n");
}

void set_specific_bits() {
    unsigned int flags = 0b10100;  // 十進(jìn)制 20
    unsigned int mask = 0b01011;   // 十進(jìn)制 11
    
    printf("\n設(shè)置特定位示例:\n");
    printf("原始標(biāo)志位: ");
    print_binary_5bit(flags);
    printf(" (%d)\n", flags);
    
    printf("設(shè)置掩碼:   ");
    print_binary_5bit(mask);
    printf(" (要設(shè)置的位)\n");
    
    printf("按位或運(yùn)算:\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的位都被設(shè)置為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;
}

運(yùn)行結(jié)果:

將數(shù)字 10 的最末位設(shè)置為1:
原始數(shù)值: 01010 (10)
掩碼 1:   00001
按位或運(yùn)算:
  01010
| 00001
  -----
  01011 (11)
→ 最末位被強(qiáng)制設(shè)置為1

將數(shù)字 15 的最末位設(shè)置為1:
原始數(shù)值: 01111 (15)
掩碼 1:   00001
按位或運(yùn)算:
  01111
| 00001
  -----
  01111 (15)
→ 最末位被強(qiáng)制設(shè)置為1

設(shè)置特定位示例:
原始標(biāo)志位: 10100 (20)
設(shè)置掩碼:   01011 (要設(shè)置的位)
按位或運(yùn)算:
  10100
| 01011
  -----
  11111 (31)
→ 掩碼中為1的位都被設(shè)置為1

2. 權(quán)限授予系統(tǒng)

#include <stdio.h>

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

// 定義權(quán)限標(biāo)志
#define READ_PERM   (1 << 0)  // 0001 - 讀權(quán)限
#define WRITE_PERM  (1 << 1)  // 0010 - 寫權(quán)限  
#define EXEC_PERM   (1 << 2)  // 0100 - 執(zhí)行權(quán)限
#define ADMIN_PERM  (1 << 3)  // 1000 - 管理員權(quán)限

void grant_permissions(unsigned int current_perm, unsigned int new_perm, const char* user) {
    printf("\n為用戶 %s 授予權(quán)限:\n", user);
    printf("當(dāng)前權(quán)限: ");
    print_binary_4bit(current_perm);
    printf("\n授予權(quán)限: ");
    print_binary_4bit(new_perm);
    printf("\n按位或運(yù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(" (新權(quán)限)\n");
    
    // 解釋權(quán)限含義
    printf("權(quán)限說明: ");
    if (result & READ_PERM) printf("讀 ");
    if (result & WRITE_PERM) printf("寫 ");
    if (result & EXEC_PERM) printf("執(zhí)行 ");
    if (result & ADMIN_PERM) printf("管理");
    printf("\n");
}

int main() {
    printf("=== 權(quán)限管理系統(tǒng) ===\n");
    
    // 初始用戶只有讀權(quán)限
    unsigned int user_perm = READ_PERM;
    
    grant_permissions(user_perm, WRITE_PERM, "張三");
    grant_permissions(user_perm | WRITE_PERM, EXEC_PERM, "張三");
    
    // 管理員一次性授予所有權(quán)限
    grant_permissions(0, READ_PERM | WRITE_PERM | EXEC_PERM, "管理員");
    
    return 0;
}

運(yùn)行結(jié)果:

=== 權(quán)限管理系統(tǒng) ===

為用戶 張三 授予權(quán)限:
當(dāng)前權(quán)限: 0001
授予權(quán)限: 0010
按位或運(yùn)算:
  0001
| 0010
  ----
  0011 (新權(quán)限)
權(quán)限說明: 讀 寫 

為用戶 張三 授予權(quán)限:
當(dāng)前權(quán)限: 0011
授予權(quán)限: 0100
按位或運(yùn)算:
  0011
| 0100
  ----
  0111 (新權(quán)限)
權(quán)限說明: 讀 寫 執(zhí)行 

為用戶 管理員 授予權(quán)限:
當(dāng)前權(quán)限: 0000
授予權(quán)限: 0111
按位或運(yùn)算:
  0000
| 0111
  ----
  0111 (新權(quán)限)
權(quán)限說明: 讀 寫 執(zhí)行

3. 組合配置標(biāo)志

#include <stdio.h>

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

// 定義配置選項(xiàng)
#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("=== 構(gòu)建配置選項(xiàng) ===\n");
    
    unsigned int config = 0;
    
    printf("初始配置: ");
    print_binary_8bit(config);
    printf("\n\n");
    
    // 逐步添加配置選項(xiàng)
    config |= OPTION_A;
    printf("添加選項(xiàng)A: ");
    print_binary_8bit(config);
    printf(" (A | 0)\n");
    
    config |= OPTION_C;
    printf("添加選項(xiàng)C: ");
    print_binary_8bit(config);
    printf(" (當(dāng)前 | C)\n");
    
    config |= OPTION_E;
    printf("添加選項(xiàng)E: ");
    print_binary_8bit(config);
    printf(" (當(dāng)前 | E)\n");
    
    // 一次性添加多個(gè)選項(xiàng)
    config |= (OPTION_B | OPTION_D);
    printf("添加B和D: ");
    print_binary_8bit(config);
    printf(" (當(dāng)前 | (B | D))\n");
    
    printf("\n最終配置: ");
    print_binary_8bit(config);
    printf(" (所有選項(xiàng)都已設(shè)置)\n");
}

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

運(yùn)行結(jié)果:

=== 構(gòu)建配置選項(xiàng) ===

初始配置: 00000000

添加選項(xiàng)A: 00000001 (A | 0)
添加選項(xiàng)C: 00000101 (當(dāng)前 | C)
添加選項(xiàng)E: 00010101 (當(dāng)前 | E)
添加B和D: 00011111 (當(dāng)前 | (B | D))

最終配置: 00011111 (所有選項(xiàng)都已設(shè)置)

重要注意事項(xiàng)

關(guān)于"最末位變成0"的說明

原文中提到"對(duì)這個(gè)數(shù)or 1之后再減一",這實(shí)際上不是推薦做法。正確的方法是使用按位與來清除位:

// ? 不推薦的做法
int number = 0b1010;  // 10
number = (number | 1) - 1;  // 變成 1001 (9)

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

總結(jié)

按位或運(yùn)算的核心用途:

  1. 設(shè)置特定位:將指定位強(qiáng)制設(shè)置為1

    • flags | mask 設(shè)置mask中所有為1的位
  2. 權(quán)限授予:添加權(quán)限而不影響其他權(quán)限

    • 用戶權(quán)限 = 當(dāng)前權(quán)限 | 新權(quán)限
  3. 配置組合:逐步構(gòu)建配置選項(xiàng)

    • 配置 = 配置 | 新選項(xiàng)
  4. 合并標(biāo)志:將多個(gè)標(biāo)志合并為一個(gè)值

優(yōu)勢(shì):

  • 非破壞性:只設(shè)置指定位,不影響其他位
  • 可組合:可以一次性設(shè)置多個(gè)位
  • 高效:?jiǎn)蝹€(gè)操作完成多個(gè)設(shè)置

按位或運(yùn)算是設(shè)置二進(jìn)制特定位的首選工具!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容