CPU向内存保存数据的方式有2种,这意味着CPU解析数据的方式也分为2种:
♦ 大端序(big endian):高位字节存放到低位地址;
♦ 小端序(little endian):高位字节存放到高位地址。
不同的机器主机字节序不相同,与CPU设计有关,数据的顺序是由CPU决定的,而与操作系统无关。我们把某个给定系统所用的字节序称为主机字节序(host byte order)。比如x86系列CPU都是little-endian的字节序。由于这个原因不同体系结构的机器之间无法通信,所以要转换成一种约定的数序,也就是网络字节顺序,采用大端序的排序方法。
Linux socket网络编程中,经常会使用下面四个C标准库函数进行字节序间的转换:
#include <arpa/inet.h> uint32_t htonl(uint32_t hostlong); //把uint32_t类型从主机序转换到网络序 uint16_t htons(uint16_t hostshort); //把uint16_t类型从主机序转换到网络序 uint32_t ntohl(uint32_t netlong); //把uint32_t类型从网络序转换到主机序 uint16_t ntohs(uint16_t netshort); //把uint16_t类型从网络序转换到主机序
如果需要对64位类型数据进行主机字节序与网络字节序的转换,没有现成系统API可用,可以通过下面两种方法进行转换:
//主机序转网络序 unsigned long long htonll(unsigned long long val) { if(__BYTE_ORDER == __LITTLE_ENDIAN) { return (((unsigned long long )htonl((int)((val << 32) >> 32))) << 32) | (unsigned int)htonl((int)(val >> 32)); } else if (__BYTE_ORDER == __BIG_ENDIAN) { return val; } } //网络序转主机序 unsigned long long ntohll(unsigned long long val) { if (__BYTE_ORDER == __LITTLE_ENDIAN) { return (((unsigned long long )ntohl((int)((val << 32) >> 32))) << 32) | (unsigned int)ntohl((int)(val >> 32)); } else if (__BYTE_ORDER == __BIG_ENDIAN) { return val; } }
根据联合体的特性:联合中所有成员引用的是内存中相同的位置,其长度为最长成员的长度:
typedef struct { unsigned int u32_h; unsigned int u32_l; }Int64_t; typedef union { unsigned long long u64; Int64_t st64; }Convert64_t; //主机序转网络序 unsigned long long htonll(unsigned long long val) { if (__BYTE_ORDER == __LITTLE_ENDIAN) { Convert64_t box_in, box_out; box_in.u64 = val; box_out.st64.u32_h = htonl(box_in.st64.u32_l); box_out.st64.u32_l = htonl(box_in.st64.u32_h); return box_out.u64; } else if (__BYTE_ORDER == __BIG_ENDIAN) { return val; } } //网络序转主机序 unsigned long long ntohll(unsigned long long val) { if (__BYTE_ORDER == __LITTLE_ENDIAN) { Convert64_t box_in, box_out; box_in.u64 = val; box_out.st64.u32_h = ntohl(box_in.st64.u32_l); box_out.st64.u32_l = ntohl(box_in.st64.u32_h); return box_out.u64; } else if(__BYTE_ORDER == __BIG_ENDIAN) { return val; } }
使用编译器内置函数:
#ifdef WIN32 #define ntohll(x) _byteswap_uint64 (x) #define htonll(x) _byteswap_uint64 (x) #else #if __BYTE_ORDER == __BIG_ENDIAN #define ntohll(x) (x) #define htonll(x) (x) #else #if __BYTE_ORDER == __LITTLE_ENDIAN #define ntohll(x) __bswap_64 (x) #define htonll(x) __bswap_64 (x) #endif #endif #endif
标签:__,box,字节,val,主机,unsigned,long,函数 From: https://www.cnblogs.com/yooouk/p/16771772.html