b = a >> (8 - 2) → 0000 0001a = a << 2 → 1110 1100a = a | b → 1110 1101 (0xED) ✓a = (a >> (8 - 2)) | (a << 2);
注意:C 標準未定義移位量 ≥ 位寬時的行為,確保 n < N。
/* 靜態斷言確保 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_rotateleft32 | rol |
| MSVC | _rotl, _rotr (intrin.h) | rol, ror |
現代編譯器在優化等級 -O2 以上時,能自動識別 (x << n) | (x >> (32-n)) 模式並產出單一 rol 指令,無需手寫內聯組語。
assert(0 < n && n < N)。uint8_t 運算前會提升為 int,巨集內以目標型別強制轉型可避免意外擴展。掌握循環移位不僅是位運算基本功,更是理解現代高效能雜湊、加密與壓縮演算法核心運算單元的入場券。