位運算讓 C 語言具備類匯編的底層操作能力,在內存受限、性能敏感、硬件交互場景不可或缺。本文系統整理六大位運算符語義、優先級、經典例程與實戰模式。
| 符號 | 名稱 | 運算規則 | 優先級 | 結合性 |
|---|---|---|---|---|
~ | 按位取反 | 單目,0→1,1→0 | 高(單目) | 右到左 |
<< | 左移 | 低位補 0,相當於 ×2n | 中 | 左到右 |
>> | 右移 | 無符號補 0,有符號視實現(通常算術移位) | 中 | 左到右 |
& | 按位與 | 同為 1 結果 1 | 低 | 左到右 |
^ | 按位異或 | 相同 0,不同 1 | 低 | 左到右 |
| | 按位或 | 有 1 結果 1 | 最低 | 左到右 |
注意:位運算優先級低於算術運算,混合使用時建議加括號,如 (a & b) + c。
#include
int main() {
short a1 = 521; // 0x0209 = 0000 0010 0000 1001
short a2 = 123; // 0x007B = 0000 0000 0111 1011
short And, Or, Not, Xor;
And = a1 & a2; // 0000 0000 0000 1001 = 9
Or = a1 | a2; // 0000 0010 0111 1011 = 635
Not = ~a1; // 1111 1101 1111 0110 = -522 (補碼)
Xor = a1 ^ a2; // 0000 0010 0111 0010 = 626
printf("a1,a2 位與: %d\n", And);
printf("a1,a2 位或: %d\n", Or);
printf("a1 位取反: %d\n", Not);
printf("a1,a2 位異或: %d\n", Xor);
return 0;
}
// 設置第 n 位
x |= (1U << n);
// 清除第 n 位
x &= ~(1U << n);
// 翻轉第 n 位
x ^= (1U << n);
// 測試第 n 位
bool is_set = (x >> n) & 1U;
// 提取連續位 [l, r]
uint32_t bits = (x >> l) & ((1U << (r - l + 1)) - 1);
// 判斷是否為 2 的冪次 (n > 0)
bool is_pow2 = (n & (n - 1)) == 0;
// 向上對齊到 2 的冪次邊界 (align 為 2 的冪次)
uint32_t aligned = (addr + align - 1) & ~(align - 1);
// 絕對值 (假設 int 32 位)
int abs_val = (x ^ (x >> 31)) - (x >> 31);
// 符號函數: 1/0/-1
int sign = (x > 0) - (x < 0); // 或位運算版
#define SWAP(a, b) do { a ^= b; b ^= a; a ^= b; } while(0)
// 注意:a 和 b 不能指向同一地址
在嵌入式系統中,將多個布爾標誌打包進單個整數:
struct Flags {
uint8_t enabled : 1;
uint8_t visible : 1;
uint8_t dirty : 1;
uint8_t reserved : 5;
} flags; // 僅佔 1 字節,而非 4 個 bool (通常 4 字節)
1 << 32 在 32 位平台未定義行為,需用 1ULL << 32。& vs &&,| vs ||,前者不短路,逐位操作。a & b == 0 實為 a & (b == 0),必須寫 (a & b) == 0。位運算是 C 語言開發者的基本功。熟練掌握掩碼構造、標誌位壓縮、無分支技巧,能寫出既優雅又高效的系統級代碼。建議收藏本文速查表,實戰中多驗證、多反思。