計算機內存中多字節數據的存儲順序稱為字節序:
例:32 位整數 0x12345678 在內存中的分布:
| 地址偏移 | 大端模式 | 小端模式 |
|---|---|---|
| 0x00 | 0x12 (高字節) | 0x78 (低字節) |
| 0x01 | 0x34 | 0x56 |
| 0x02 | 0x56 | 0x34 |
| 0x03 | 0x78 (低字節) | 0x12 (高字節) |
IP 180.97.33.107 → 十六進制 0xB461216B(網絡序)。主機為小端,內存中實際存儲為 0x6B2161B4。
#include <stdio.h>
#include <string.h>
int ip_to_host(const char *ip_str) {
unsigned char bytes[4];
sscanf(ip_str, "%hhu.%hhu.%hhu.%hhu", &bytes[0], &bytes[1], &bytes[2], &bytes[3]);
// 手動構造主機序整數(小端:低地址存低字節)
return (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
}
int main() {
const char *ip = "180.97.33.107";
int host_val = ip_to_host(ip);
printf("IP: %s\nHost order (hex): %x\n", ip, host_val); // 輸出 6b2161b4
return 0;
}
// 方法一:指針交換字節
unsigned int htonl_v1(unsigned int host) {
unsigned char *p = (unsigned char *)&host;
unsigned char tmp;
tmp = p[0]; p[0] = p[3]; p[3] = tmp;
tmp = p[1]; p[1] = p[2]; p[2] = tmp;
return host;
}
// 方法二:位運算(推薦,無類型懲罰風險)
unsigned int htonl_v2(unsigned int host) {
return ((host & 0xFF) << 24) |
((host >> 8 & 0xFF) << 16) |
((host >> 16 & 0xFF) << 8) |
(host >> 24 & 0xFF);
}
char *net_to_ip_str(unsigned int net) {
static char buf[16];
sprintf(buf, "%u.%u.%u.%u",
(net >> 24) & 0xFF,
(net >> 16) & 0xFF,
(net >> 8) & 0xFF,
net & 0xFF);
return buf;
}
實際開發中應直接使用標準庫函數,保證可移植性:
inet_aton():字符串 IP → 網絡序 in_addrinet_ntoa():網絡序 in_addr → 字符串 IPhtonl() / ntohl():32 位主機序↔網絡序htons() / ntohs():16 位主機序↔網絡序int is_little_endian() {
union { int i; char c[4]; } u = {1};
return u.c[0] == 1; // 低地址存低字節即為小端
}
int a = 0x61; // 97
printf("%x\n", *(char *)&a); // 輸出 61 → 小端機
輸出低字節 0x61 證明為小端存儲。