首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言位元運算完全指南:&、|、^、~、<<、>> 實戰技巧

     編輯:關於C語言

六大位元運算子速查表

運算子名稱規則典型用途
&按位與 (AND)同為 1 → 1,否則 0清零、取指定位、檢查旗標
|按位或 (OR)任一為 1 → 1置位、合併旗標
^按位異或 (XOR)相異 → 1,相同 → 0翻轉位、交換變數、簡易加密
~按位取反 (NOT)0↔1產生遮罩、取反
<<左移高位捨棄,低位補 0乘 2^n、組合欄位
>>右移無號補 0,有號算術移位(補符號位)除 2^n、提取高位

核心技巧:遮罩模式


// 1. 清零第 n 位 (n=0 為最低位)
x &= ~(1u << n);

// 2. 置 1 第 n 位
x |= (1u << n);

// 3. 翻轉第 n 位
x ^= (1u << n);

// 4. 讀取第 n 位 (0/1)
bool bit = (x >> n) & 1u;

// 5. 連續欄位操作:[low, high]
uint32_t mask = ((1u << (high - low + 1)) - 1) << low;
x &= ~mask;          // 清零欄位
x |= (val << low) & mask; // 寫入新值

經典應用場景

1. 高效乘除 2 的冪次


x <<= 3;  // x *= 8
x >>= 2;  // x /= 4 (無號/正數)

編譯器優化時自動轉換,但嵌入式/DSP 手寫更可控。

2. 交換兩整數(無暫存變數)


a ^= b; b ^= a; a ^= b; // 僅適用整數,浮點數不可

3. 判斷 2 的冪次


bool is_pow2(unsigned x) { return x && !(x & (x - 1)); }
// 原理:2^n 二進位僅一個 1;x-1 將該 1 變 0、低位全變 1 → & 結果為 0

4. 計算人口數量


// Kernighan 算法:每次清除最低位 1
int popcount(unsigned x) {
    int c = 0;
    while (x) { x &= x - 1; ++c; }
    return c;
}
// 現代 CPU 內建指令:__builtin_popcount / _mm_popcnt_u32

5. 位元欄位打包(網路協議、暇存器)


struct Reg {
    uint32_t enable : 1;
    uint32_t mode   : 3;
    uint32_t reserved: 28;
};
// 讀寫自動對應移位/遮罩,但位元順序、對齊由編譯器決定,跨平台需謹慎

進階陷阱與避坑

1. 移位寬度 ≥ 型別寬度 → 未定義行為


uint32_t x = 1;
x <<= 32; // UB!C 標準:移位量必須 < 32

防禦:x <<= (n & 31) 或分兩步移位。

2. 有號右移實作定義

負數 >> 補 1 (算術移位) 或補 0 (邏輯移位) 取決於編譯器。**可移植代碼避免有號右移**,改用無號型別或手動處理符號。

3. 字面值預設為 int,遮罩需加 u/U


x &= ~(1 << 31); // 1 為 int,1<<31 可能溢位/符號擴展
x &= ~(1u << 31); // 正確:無號運算,行為明確

4. 不同寬度運算元的整數提升


uint8_t a = 0xFF, b = 0x01;
auto c = a & b; // a、b 先提升為 int,再 &,結果型別為 int
// 若需保持 8 位:static_cast<uint8_t>(a & b)

複合賦值運算子

&= | = ^= <<= >>= 皆為對應運算 + 賦值的語法糖,具原子性(單執行緒)且更易讀。

總結

位元運算是系統程式、嵌入式、演優化的基石。熟練掌握「遮罩模式」、移位陷阱、無號型別原則,能寫出無分支、常數時間、極致高效的核心邏輯。現代編譯器對簡單位元運算優化極佳,**可讀性優先**,關鍵熱點再手工微調。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved