字節序由 CPU 架構決定,是跨平台數據交換、二進制文件解析、網絡協議實現的核心知識點。本文涵蓋大小端判斷、結構體位域位序、網絡字節序轉換函數、移植性編程最佳實踐。
| 模式 | 代表架構 | 低地址存儲 | 高地址存儲 | 圖示 (0x12345678) |
| 大端 | PowerPC, SPARC, Network | 高位字節 (0x12) | 低位字節 (0x78) | 12 34 56 78 |
| 小端 | x86, ARM (默認), RISC-V | 低位字節 (0x78) | 高位字節 (0x12) | 78 56 34 12 |
二、運行時檢測代碼
#include
int main() {
int i = 0x12345678;
char *p = (char*)&i;
printf("低地址字節: 0x%02x\n", *p); // 小端輸出 0x78,大端 0x12
return 0;
}
三、結構體位域與位序
struct {
unsigned int a : 4; // 低 4 位
unsigned int b : 4; // 高 4 位
} bit;
規則:位域分配順序與字節序一致。小端機器從低位向高位分配(a 佔低 4 位),大端從高位向低位分配。跨平台二進制接口嚴禁使用位域,改用掩碼移位手動打包。
四、網絡字節序轉換
#include
// 主機序 → 網絡序 (大端)
uint32_t htonl(uint32_t hostlong); // 32 位
uint16_t htons(uint16_t hostshort); // 16 位
// 網絡序 → 主機序
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
鐵律:所有網絡傳輸的整數(IP、端口、協議頭長度、序列號)發送前必須 htonl/htons,接收後必須 ntohl/ntohs,無論當前主機是大端還是小端。
五、IP 地址字節序實例
// 192.168.1.100 -> 0xC0A80164
uint32_t ip = inet_addr("192.168.1.100"); // 返回網絡序
struct in_addr addr; addr.s_addr = ip;
printf("%s\n", inet_ntoa(addr)); // 打印點分十進制
// 手動構造
uint32_t ip = htonl((192<<24) | (168<<16) | (1<<8) | 100);
六、移植性編程檢查清單
- 結構體網絡傳輸前:逐字段
htonl/htons,或使用打包函數序列化,不可直接 memcpy 結構體發送(填充字節、位域、對齊差異)。
- 文件格式解析:明確規範字節序(如 BMP 小端、JPEG 大端),讀取時按規範轉換。
- 共享內存/進程間通訊:約定統一字節序(推薦網絡序)。
- 調試技巧:
od -x / xxd 查看原始字節序,對比預期值。
- 上一篇文章: SDL2 開發入門:從編譯安裝到首個渲染窗口完整指南
- 下一篇文章: C 語言實現 BMP 彩色圖片轉二值圖像:文件格式解析、灰度化與閾值分割全流程
Copyright ©
程式碼之家 All Rights Reserved