循環移位 與邏輯/算術移位的本質區別在於:**移出的位不丟失,而是環回填充另一端**。
廣泛應用於:加密算法、壓縮編碼、硬件寄存器操作、網絡協議校驗和、位圖處理等系統級編程場景。
以 8 位無符號數 a = 0b01111011 (0x7B) 為例,**循環左移 2 位** 期望結果 0b11101101 (0xED)。
b = a >> (8 - 2) → a >> 6 → 0b00000001 (高 2 位 01 移至最低位)a = a << 2 → 0b11101100 (高 2 位 01 丟失,低位補 0)a = a | b → 0b11101100 | 0b00000001 = 0b11101101 ✅a = (a >> (8 - 2)) | (a << 2);
| 操作 | 公式 | 說明 |
|---|---|---|
| 循環左移 n 位 | (x >> (N - n)) | (x << n) | 高 n 位移至低位,低位左移 n 位 |
| 循環右移 n 位 | (x << (N - n)) | (x >> n) | 低 n 位移至高位,高位右移 n 位 |
常見位寬 N:8 (uint8_t)、16 (uint16_t)、32 (uint32_t)、64 (uint64_t)。
#include <stdint.h>
#include <limits.h> // CHAR_BIT
// 靜態斷言確保無符號類型
#define ROL(x, n, bits) (((x) << (n)) | ((x) >> ((bits) - (n))))
#define ROR(x, n, bits) (((x) >> (n)) | ((x) << ((bits) - (n))))
// 類型安全封裝:僅支持標準無符號整型
static inline uint8_t rotl8 (uint8_t x, unsigned n) { return ROL(x, n, 8); }
static inline uint8_t rotr8 (uint8_t x, unsigned n) { return ROR(x, n, 8); }
static inline uint16_t rotl16(uint16_t x, unsigned n) { return ROL(x, n, 16); }
static inline uint16_t rotr16(uint16_t x, unsigned n) { return ROR(x, n, 16); }
static inline uint32_t rotl32(uint32_t x, unsigned n) { return ROL(x, n, 32); }
static inline uint32_t rotr32(uint32_t x, unsigned n) { return ROR(x, n, 32); }
static inline uint64_t rotl64(uint64_t x, unsigned n) { return ROL(x, n, 64); }
static inline uint64_t rotr64(uint64_t x, unsigned n) { return ROR(x, n, 64); }
// 使用示例
#include <stdio.h>
int main() {
uint8_t a = 0x7B; // 01111011
printf("ROL2: 0x%02X\n", rotl8(a, 2)); // 0xED (11101101)
printf("ROR3: 0x%02X\n", rotr8(a, 3)); // 0xBB (10111011)
return 0;
}
n 必須 0 <= n < N。n >= N 或 n < 0 導致未定義行為。實際工程中建議加 n %= N 或斷言。uintN_t**。(x << n) | (x >> (N-n)) 模式,會直接生成單條 CPU 指令 (ROL/ROR)。無需手寫彙編。<bit> 提供 std::rotl/std::rotr,C 開發者可參考實現或期待 C23 標準化。循環移位 = **提取溢出位 + 普通移位 + 合併**。掌握通用公式 (x << n) | (x >> (N-n)) 及其鏡像,配合 uintN_t 類型安全封裝,即可在任何C項目中高效、可移植地實現循環移位。這正是C語言位運算「贴近硬件、零開銷抽象」魅力的典型體現。