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

C 語言基礎教程(二):位元運算子完整指南——AND/OR/XOR/NOT、移位、循環移位實作與陷阱

     編輯:C 語言基礎

位元運算子:C 語言貼近硬體的利器

僅適用於整數與字元型別 (及其變體),對浮點數無效。結果可為 0/1 以外值,區別於邏輯運算。

六大位元運算子

運算子名稱功能範例 (x=7=0111, y=8=1000)
&位元 AND對應位皆 1 才為 1x & y = 0
|位元 OR對應位任一 1 即為 1x | y = 15 (1111)
^位元 XOR對應位不同為 1x ^ y = 15
~位元 NOT (補數)逐位翻轉~x = ...11111000 (-8)
<<左移低位補 0,高位捨棄x << 1 = 14 (1110)
>>右移無號補 0,有號實作定義 (通常算術右移複製符號位)x >> 1 = 3 (0011)

位元 vs 邏輯運算子關鍵差異


int x = 7;
x && 8   == 1   /* 邏輯與:非零且非零 → 真 (1) */
x & 8    == 0   /* 位元與:0111 & 1000 = 0000 */

移位運算細節與陷阱

  • 非循環:移出位元捨棄,另一端補 0 (無號) 或符號位 (有號)。
  • 移位量 ≥ 位寬 = UB:x << 32 在 32-bit int 未定義。
  • 有號負數右移:C 標準為實作定義,可攜程式僅對無號型別移位。
  • 字元自動提升:char c; c << 2 中 c 先提升為 int 再移位。

循環移位 (Rotate) 純 C 實作

標準庫無內建,需自行組合:


/* 32-bit 無號整數循環左移 n 位 (0 < n < 32) */
uint32_t rotl32(uint32_t x, int n)
{
    return (x << n) | (x >> (32 - n));
}

/* 循環右移 */
uint32_t rotr32(uint32_t x, int n)
{
    return (x >> n) | (x << (32 - n));
}

/* 通用巨集 (需自行確保 0 < n < N) */
#define ROL(x, n, N) (((x) << (n)) | ((x) >> ((N) - (n))))
#define ROR(x, n, N) (((x) >> (n)) | ((x) << ((N) - (n))))

編譯器內建函數 (現代編譯器優化可識別上述模式)

編譯器內建函數標頭檔
GCC/Clang__builtin_rotateleft32, __builtin_rotateright32無需
MSVC_rotl, _rotr

常見應用場景

  1. 位元旗標操作:flags |= MASK; flags &= ~MASK; flags ^= MASK;
  2. 快速乘除 2 的冪次:x << 3 (×8), x >> 2 (÷4)。
  3. 大小端轉換:(x << 24) | ((x << 8) & 0xFF0000) | ((x >> 8) & 0xFF00) | (x >> 24)。
  4. 雜湊/加密攪拌:MurmurHash, xxHash, AES, SHA 大量使用旋轉、XOR、移位。
  5. 嵌入式暫存器操作:REG |= (1 << BIT); 設定位,REG &= ~(1 << BIT); 清除位。

避坑清單

  1. 對有號整數右移 (行為不確定)。
  2. 移位量可能 ≥ 位寬 (UB)。
  3. 混淆 & (位元和) 與 && (邏輯與)。
  4. 修改字串常值指標指向的記憶體 (UB)。
  5. 假設 ~x + 1 == -x 適用於無號數 (會溢位)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved