位元組序(Endianness)決定多位元組資料在記憶體中的排列順序,是跨平台資料交換、網路程式設計、二進位檔案處理、嵌入式開發的核心議題。本文深入剖析大小端原理、檢測方法、轉換函式與實務應用。
以 16 位整數 0x0102 為例:
| 模式 | 低位址 | 高位址 | 典型架構 |
|---|---|---|---|
| 大端序 | 高位元組 0x01 | 低位元組 0x02 | 網路序、PowerPC、SPARC、MIPS |
| 小端序 | 低位元組 0x02 | 高位元組 0x01 | x86、x86-64、ARM(預設) |
#include <stdio.h>
int main() {
union {
short s;
char c[sizeof(short)];
} un;
un.s = 0x0102;
printf("char size: %lu byte\n", sizeof(char));
if (sizeof(short) == 2) {
if (un.c[0] == 1 && un.c[1] == 2)
printf("Big-endian\n");
else if (un.c[0] == 2 && un.c[1] == 1)
printf("Little-endian\n");
else
printf("Unknown\n");
} else {
printf("short size: %lu\n", sizeof(short));
}
return 0;
}
short 後,透過 char 陣列檢視各位元組內容c[0] 對應低位址,c[1] 對應高位址arpa/inet.h / winsock2.h 提供:
| 函式 | 轉換方向 | 適用 |
|---|---|---|
htons | Host → Network Short (16-bit) | 埠號 |
htonl | Host → Network Long (32-bit) | IPv4 位址 |
ntohs | Network → Host Short | 接收埠號 |
ntohl | Network → Host Long | 接收 IPv4 |
uint16_t htons_manual(uint16_t x) {
return (x >> 8) | (x << 8);
}
uint32_t htonl_manual(uint32_t x) {
return ((x >> 24) & 0xFF) |
((x >> 8) & 0xFF00) |
((x << 8) & 0xFF0000) |
((x << 24) & 0xFF000000);
}
直接強制轉型存取可能違反嚴格別名規則,導致未定義行為:
int x = 0x01020304; char *p = (char *)&x; // 可能觸發嚴格別名優化問題
安全做法:
memcpy 複製到目標型別變數uint8_t 陣列手動組裝/解析#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
// 小端序編譯期常數
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
// 大端序編譯期常數
#endif
理解並正確處理位元組序,是編寫可移植、健壯系統軟體的必備技能。建議在專案中統一使用標準轉換函式,並在序列化/反序列化層集中處理端序轉換。