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

C語言位元運算實戰技巧:移位、邏輯運算符七大經典應用

     編輯:關於C

前言

位元運算是系統程式、嵌入式開發、演算法優化的核心利器。本文整理七大經典位元運算實戰技巧,涵蓋計數、提取、判斷、反轉、平均、找單一、異或應用,附完整 C 程式碼與原理解析。

技巧一:計算二進制中 1 的個數(Brian Kernighan 算法)

int count_one_bits(unsigned int value) {
    int count = 0;
    while (value) {
        value &= (value - 1); // 清除最低位的 1
        count++;
    }
    return count;
}

原理:`value - 1` 會將最低位的 1 變 0,低位 0 變 1;`&` 運算恰好清除該 1。每次迴圈消除一個 1,迴圈次數 = 1 的個數。時間複雜度 O(k),k 為 1 的個數。

技巧二:提取整數的奇數位與偶數位

void print_odd_even_bits(int num) {
    int odd[16], even[16];
    // 奇數位(bit 1,3,5... 即第 0,2,4... 索引)
    for (int i = 0, j = 0; j < 32; i++, j += 2)
        odd[15-i] = (num >> j) & 1;
    // 偶數位(bit 0,2,4... 即第 1,3,5... 索引)
    for (int i = 0, j = 1; j < 32; i++, j += 2)
        even[15-i] = (num >> j) & 1;

    printf("奇數位(高->低): ");
    for (int i = 0; i < 16; i++) printf("%d ", odd[i]);
    printf("\n偶數位(高->低): ");
    for (int i = 0; i < 16; i++) printf("%d ", even[i]);
    printf("\n");
}

※ 注意:位元索引通常從 0 起算(LSB 為第 0 位),文中「奇數位」實為索引為偶數的位元。

技巧三:判斷排名是否連續(位元遮罩法)

// 假設排名範圍 1~5,對應 bit 0~4
int ranks[5] = {a, b, c, d, e};
int mask = 0;
for (int i = 0; i < 5; i++)
    mask |= (1 << (ranks[i] - 1)); // 設定對應位

// 檢查是否連續:連續 n 個 1 形式為 (1<

技巧四:計算兩數二進制不同位數(漢明距離)

int different_bits(int m, int n) {
    int xor = m ^ n;       // 不同位為 1
    return count_one_bits(xor); // 復用技巧一
}

異或完美識別差異位,配合計數 1 的演算法極為高效。

技巧五:無符號整數二進制位元反轉

unsigned int reverse_bits(unsigned int num) {
    unsigned int ret = 0;
    for (int i = 0; i < 32; i++) {
        ret <<= 1;                    // 左移騰出最低位
        ret |= (num >> i) & 1;        // 取 num 第 i 位填入
    }
    return ret;
}

從低位到高位依次取出,構建反轉後的數值。可優化為查表法(8-bit 查表 4 次)提升速度。

技巧六:無溢出計算兩數平均值

int average(int a, int b) {
    // (a & b) 保留共同的 1(進位部分)
    // (a ^ b) >> 1 計算不產生進位的平均
    return (a & b) + ((a ^ b) >> 1);
}

原理證明:`a + b = (a ^ b) + 2*(a & b)` → `(a+b)/2 = (a&b) + ((a^b)>>1)`。完全避免 `a+b` 溢出。

技巧七:找出陣列中唯一出現一次的數字(其餘皆出現兩次)

int find_single(int arr[], int size) {
    int result = 0;
    for (int i = 0; i < size; i++)
        result ^= arr[i]; // 相同數異或為 0,0 異或 x = x
    return result;
}

異或性質:`x ^ x = 0`,`x ^ 0 = x`,滿足交換律與結合律。成對數字抵消為 0,單獨者保留。

綜合測試主程式

int main() {
    printf("count_one_bits(15)=%d\n", count_one_bits(15)); // 4
    print_odd_even_bits(0b10101010);
    int ranks[] = {1,2,3,4,5};
    // ... 測試其他函式
    return 0;
}

總結速查表

需求核心運算關鍵性質
計數 1`x &= x-1`每次清除最低位 1
提取位`(x>>k)&1`右移歸位 + 遮罩
設定位`x |= (1<或運算置 1
清除位`x &= ~(1<與運算置 0
翻轉位`x ^= (1<異或翻轉
檢測 2 的冪次`x && !(x & (x-1))`僅有一個 1
無溢出平均`(a&b)+((a^b)>>1)`分解進位與非進位
找單一數`xor` 累積成對抵消

結語

位元運算看似晦澀,實則是電腦最原生的語言。熟練掌握上述技巧,能在演算法競賽、系統優化、硬體驅動、加密演算等領域寫出極致高效的程式碼。建議多動手實驗,觀察二進制變化,建立直覺理解。

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