Linux 內核中蘊含大量經典位操作算法,其中字節序轉換(高低位交換)是網絡編程、文件格式解析、驅動開發的高頻需求。本文提煉內核源碼中的 bswap_8/16/32 實現,詳細解析位運算邏輯,附完整可運行代碼與測試結果。
#include/* 8 位:交換高低 4 位(半字節交換) */ static inline unsigned char bswap_8(unsigned char v) { return ((v & 0xff) << 4) | (v >> 4); } /* 16 位:交換高低 8 位(字節交換) */ static inline unsigned short bswap_16(unsigned short v) { return ((v & 0xff) << 8) | (v >> 8); } /* 32 位:交換高低 16 位(雙字交換),實際為完整字節序反轉 */ static inline unsigned int bswap_32(unsigned int v) { return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24); }
原值: 0xAB = 1010 1011 v & 0xff = 0xAB (v & 0xff) << 4 = 1011 0000 (0xB0) ← 低 4 位移到高 4 位 v >> 4 = 0000 1010 (0x0A) ← 高 4 位移到低 4 位 結果: 0xB0 | 0x0A = 0xBA = 1011 1010
原值: 0x1234 = 00010010 00110100 (v & 0xff) << 8 = 00110100 00000000 (0x3400) ← 低字節移到高字節 v >> 8 = 00000000 00010010 (0x0012) ← 高字節移到低字節 結果: 0x3400 | 0x0012 = 0x3412
原值: 0x11223344 第 1 字節 (最低): 0x44 → 移至最高位: 0x44000000 第 2 字節: 0x33 → 移至次高位: 0x00330000 第 3 字節: 0x22 → 移至次低位: 0x00002200 第 4 字節 (最高): 0x11 → 移至最低位: 0x00000011 結果: 0x44332211 掩碼與移位組合完美實現無分支字節序轉換。
int main() {
unsigned short v = 0x1000;
printf("1、\n原來的 v: %d (0x%x)\n", v, v);
printf("16位高低8位轉換後: %d (0x%x) =========> 0x%x ---> %d\n",
v, v, bswap_16(v), bswap_16(v));
unsigned char a = 0x0a;
printf("\n2、\n原來的 a: %d (0x%x)\n", a, a);
printf("8位高低4位轉換後: %d (0x%x) ===========> 0x%x ---> %d\n",
a, a, bswap_8(a), bswap_8(a));
unsigned int b = 0x00001111;
printf("\n3、\n原來的 b: %d (0x%x)\n", b, b);
printf("32位高低16位轉換後: %d (0x%x) ========> 0x%x ---> %d\n",
b, b, bswap_32(b), bswap_32(b));
return 0;
}
1、 原來的 v: 4096 (0x1000) 16位高低8位轉換後: 4096 (0x1000) =========> 0x0010 ---> 16 2、 原來的 a: 10 (0xa) 8位高低4位轉換後: 10 (0xa) ===========> 0xa0 ---> 160 3、 原來的 b: 4369 (0x1111) 32位高低16位轉換後: 4369 (0x1111) ========> 0x11110000 ---> 286326784
驗證:
// 64 位版本(內核常用 __swab64)
static inline unsigned long long bswap_64(unsigned long long v) {
return ((v & 0xffULL) << 56) |
((v & 0xff00ULL) << 40) |
((v & 0xff0000ULL) << 24) |
((v & 0xff000000ULL) << 8) |
((v & 0xff00000000ULL) >> 8) |
((v & 0xff0000000000ULL) >> 24) |
((v & 0xff000000000000ULL) >> 40) |
(v >> 56);
}
// 現代 C 直接使用標準庫(GCC/Clang/MSVC 均內建優化)
#include // Linux
// 或 #include // bswap_16/32/64
// Windows: _byteswap_ushort/ulong/uint64
Linux 內核的 bswap 系列展示了無分支、純位運算的極致優雅:
& 0xff 等隔離目標字節/半字節。<< / >> 將片段移至目標位置。| 組裝最終結果。這類代碼無循環、無分支、指令極少,編譯器極易優化為單條指令(如 x86 bswap、ARM rev)。掌握這套模板,應對任意位寬字節序轉換得心應手。