| 運算子 | 名稱 | 規則 | 典型用途 |
|---|---|---|---|
& | 按位與 (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; // 寫入新值
x <<= 3; // x *= 8
x >>= 2; // x /= 4 (無號/正數)
編譯器優化時自動轉換,但嵌入式/DSP 手寫更可控。
a ^= b; b ^= a; a ^= b; // 僅適用整數,浮點數不可
bool is_pow2(unsigned x) { return x && !(x & (x - 1)); }
// 原理:2^n 二進位僅一個 1;x-1 將該 1 變 0、低位全變 1 → & 結果為 0
// Kernighan 算法:每次清除最低位 1
int popcount(unsigned x) {
int c = 0;
while (x) { x &= x - 1; ++c; }
return c;
}
// 現代 CPU 內建指令:__builtin_popcount / _mm_popcnt_u32
struct Reg {
uint32_t enable : 1;
uint32_t mode : 3;
uint32_t reserved: 28;
};
// 讀寫自動對應移位/遮罩,但位元順序、對齊由編譯器決定,跨平台需謹慎
uint32_t x = 1;
x <<= 32; // UB!C 標準:移位量必須 < 32
防禦:x <<= (n & 31) 或分兩步移位。
負數 >> 補 1 (算術移位) 或補 0 (邏輯移位) 取決於編譯器。**可移植代碼避免有號右移**,改用無號型別或手動處理符號。
int,遮罩需加 u/U
x &= ~(1 << 31); // 1 為 int,1<<31 可能溢位/符號擴展
x &= ~(1u << 31); // 正確:無號運算,行為明確
uint8_t a = 0xFF, b = 0x01;
auto c = a & b; // a、b 先提升為 int,再 &,結果型別為 int
// 若需保持 8 位:static_cast<uint8_t>(a & b)
&= | = ^= <<= >>= 皆為對應運算 + 賦值的語法糖,具原子性(單執行緒)且更易讀。
位元運算是系統程式、嵌入式、演優化的基石。熟練掌握「遮罩模式」、移位陷阱、無號型別原則,能寫出無分支、常數時間、極致高效的核心邏輯。現代編譯器對簡單位元運算優化極佳,**可讀性優先**,關鍵熱點再手工微調。