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

C 語言位運算實現循環移位:原理、範例與通用巨集

     編輯:C 語言基礎

循環移位 vs 邏輯移位:差在「位元不丟失」

  • 邏輯左移 (<<):高位捨棄,低位補 0。
  • 邏輯右移 (>>):低位捨棄,高位補 0 (無號) 或複製符號位 (有號)。
  • 循環左移 (ROL):高位移出的位元「繞」到低位。
  • 循環右移 (ROR):低位移出的位元「繞」到高位。

逐步拆解:8-bit 值 0x7B (0111 1011) 循環左移 2 位

  1. 取出即將被左移丟失的高 2 位:b = a >> (8 - 2) → 0000 0001
  2. 執行普通左移:a = a << 2 → 1110 1100
  3. 合併:a = a | b → 1110 1101 (0xED) ✓

無暫存變數單行寫法

a = (a >> (8 - 2)) | (a << 2);

注意:C 標準未定義移位量 ≥ 位寬時的行為,確保 n < N。

通用巨集 (支援 8/16/32/64-bit)

/* 靜態斷言確保 N 為 2 的冪次且 n 在範圍內 */
#define ROL(x, n, N) (((x) >> ((N) - (n))) | ((x) << (n)))
#define ROR(x, n, N) (((x) << ((N) - (n))) | ((x) >> (n)))

/* 針對常見寬度的便利巨集 */
#define ROL8(x, n)  ROL((uint8_t)(x),  (n), 8)
#define ROR8(x, n)  ROR((uint8_t)(x),  (n), 8)
#define ROL16(x, n) ROL((uint16_t)(x), (n), 16)
#define ROR16(x, n) ROR((uint16_t)(x), (n), 16)
#define ROL32(x, n) ROL((uint32_t)(x), (n), 32)
#define ROR32(x, n) ROR((uint32_t)(x), (n), 32)
#define ROL64(x, n) ROL((uint64_t)(x), (n), 64)
#define ROR64(x, n) ROR((uint64_t)(x), (n), 64)

實測範例

#include <stdio.h>
#include <stdint.h>

int main(void)
{
    uint8_t  a8  = 0x7B;  printf("ROL8(0x7B,2)=0x%02X\n", ROL8(a8,  2));  // 0xED
    uint16_t a16 = 0x1234; printf("ROL16(0x1234,4)=0x%04X\n", ROL16(a16, 4)); // 0x2341
    uint32_t a32 = 0x80000000; printf("ROR32(0x80000000,1)=0x%08X\n", ROR32(a32, 1)); // 0x40000000
    return 0;
}

進階議題:編譯器內建函數與硬體指令

編譯器內建函數對應指令 (x86)
GCC/Clang__builtin_rotateleft32rol
MSVC_rotl, _rotr (intrin.h)rol, ror

現代編譯器在優化等級 -O2 以上時,能自動識別 (x << n) | (x >> (32-n)) 模式並產出單一 rol 指令,無需手寫內聯組語。

常見陷阱

  1. 有號整數右移:C 標準規定實作定義 (通常為算術右移),循環移位必須使用無號型別。
  2. 移位量為 0 或 ≥ 位寬:未定義行為 (UB),巨集使用前請自行 assert(0 < n && n < N)。
  3. 型別提升:uint8_t 運算前會提升為 int,巨集內以目標型別強制轉型可避免意外擴展。

應用場景

  • 加密演算法 (AES、SHA、RC4 的 S-box 置換)
  • 雜湊函數 (MurmurHash、xxHash 的攪拌步驟)
  • 位元組序轉換 (大小端交換)
  • 嵌入式周邊暫存器位元操作
  • 圖形學:纹理座標環繞、位圖旋轉

掌握循環移位不僅是位運算基本功,更是理解現代高效能雜湊、加密與壓縮演算法核心運算單元的入場券。

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