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

C語言位運算符完整指南:技巧、應用與經典面試題

     編輯:關於C

位運算符基礎

運算符名稱規則典型用途
&按位與同為1才為1清零特定位、取指定位
|按位或有1即為1置位特定位
^按位異或不同為1翻轉特定位、無暫存變數交換
~按位取反0↔1產生遮罩、補碼運算
<<左移低位補0,高位捨棄乘 2ⁿ、組合旗標
>>右移算術/邏輯視實作除 2ⁿ、提取高位

核心應用技巧速查


// 假設 int 32位,k 為位索引 (0-based)

// 1. 判斷奇偶
(x & 1) == 0  // 偶數
(x & 1) == 1  // 奇數

// 2. 取第 k 位
(x >> k) & 1

// 3. 清零第 k 位
x &= ~(1 << k)

// 4. 置 1 第 k 位
x |= (1 << k)

// 5. 翻轉第 k 位
x ^= (1 << k)

// 6. 循環左移 k 位 (32位)
x = (x << k) | (x >> (32 - k))

// 7. 循環右移 k 位
x = (x >> k) | (x << (32 - k))

// 8. 無暫存變數交換
x ^= y; y ^= x; x ^= y;

// 9. 絕對值 (無分支)
int y = x >> 31;
return (x ^ y) - y;

// 10. 平均值 (防溢位)
(x & y) + ((x ^ y) >> 1)

// 11. 判斷 2 的冪次
(x & (x - 1)) == 0 && x != 0

// 12. 取模優化 (2ⁿ)
x % (1 << n)  →  x & ((1 << n) - 1)

// 13. 乘法優化 (2ⁿ)
x * (1 << n)  →  x << n

// 14. 除法優化 (2ⁿ)
x / (1 << n)  →  x >> n  (僅非負數安全)

補碼運算恆等式


-x       = ~x + 1 = ~(x - 1)
~x       = -x - 1
-(~x)    = x + 1
~(-x)    = x - 1
x + y    = x - ~y - 1 = (x | y) + (x & y)
x - y    = x + ~y + 1 = (x | ~y) - (~x & y)
x ^ y    = (x | y) - (x & y)
x | y    = (x & ~y) + y
x & y    = (~x | y) - ~x

比較運算位元實作 (無分支)


// 有號整數
x == y:  ~(x - y | y - x)
x != y:  x - y | y - x
x <  y:  (x - y) ^ ((x ^ y) & ((x - y) ^ x))
x <= y:  (x | ~y) & ((x ^ y) | ~(y - x))

// 無號整數
x <  y:  (~x & y) | ((~x | y) & (x - y))
x <= y:  (~x | y) & ((x ^ y) | ~(y - x))

實用巨集定義


#define SET_BIT(x, y)   ((x) |= (1 << ((y)-1)))
#define GET_BIT(x, y)   (((x) >> ((y)-1)) & 1)
#define ROT_LEFT(x, k)  ((x) << (k) | (x) >> (32 - (k)))
#define ROT_RIGHT(x, k) ((x) >> (k) | (x) << (32 - (k)))
#define IS_POW2(x)      (((x) & ((x)-1)) == 0 && (x) != 0)
#define OPPOSITE(x)     (~(x) + 1)
#define ABS(x)          ((x) ^ ((x) >> 31)) - ((x) >> 31)
#define AVG(x, y)       ((x & y) + ((x ^ y) >> 1))

完整驗證程式


#include 
#include 

#define SET_BIT(x, y)   ((x) |= (1 << ((y)-1)))
#define GET_BIT(x, y)   (((x) >> ((y)-1)) & 1)
#define ROT_RIGHT(x, k) ((x) >> (k) | (x) << (32 - (k)))
#define IS_POW2(x)      (((x) & ((x)-1)) == 0 && (x) != 0)
#define OPPOSITE(x)     (~(x) + 1)

int avg(int x, int y) { return (x & y) + ((x ^ y) >> 1); }
bool is_pow2(int x) { return (x & (x - 1)) == 0 && x != 0; }
void swap(int *x, int *y) { *x ^= *y; *y ^= *x; *x ^= *y; }

int main() {
    int a = 0x0D;  // 1101
    printf("a=%d\n", a);
    printf("bit2=%d\n", GET_BIT(a, 2));
    SET_BIT(a, 2);
    printf("set bit2: a=%d, bit2=%d\n", a, GET_BIT(a, 2));
    
    int c = ROT_RIGHT(a, 33%32);
    printf("rot right 1: c=%d, bit5=%d\n", c, GET_BIT(c, 5));
    
    printf("avg(8,692)=%d\n", avg(8, 692));
    
    for (int i = 0; i < 1000; i++)
        if (IS_POW2(i)) printf("%-5d", i);
    printf("\n");
    
    int x = 10, y = 90;
    swap(&x, &y);
    printf("swap: x=%d, y=%d\n", x, y);
    
    printf("OPPOSITE(-705)=%d\n", OPPOSITE(-705));
    return 0;
}

面試高頻考點

  1. 無暫存變數交換:理解 XOR 特性,注意 x=y 時歸零問題
  2. 判斷 2 的冪次:x & (x-1) 清除最低位 1,結果為 0 則只有一個 1
  3. 平均值防溢位:(x&y) + ((x^y)>>1) 分解為共同位 + 差異位一半
  4. 絕對值無分支:利用算術右移複製符號位
  5. 位運算優化除模乘:僅適用 2 的冪次,有號數右移需謹慎

避坑指南

  • 移位超寬度:1 << 32 未定義行為,需 1ULL << 32
  • 有號數右移:算術/邏輯移位視實作定義,可移植代碼避免依賴
  • 優化前提:編譯器 -O2 通常自動優化乘除模,手動優化需測試驗證
  • 可讀性權衡:關鍵路徑加註解,非熱點優先清晰代碼
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved