long, double类型的大小端处理 | 您所在的位置:网站首页 › 如何设置double类型 › long, double类型的大小端处理 |
首先简要说明一下数据大小端模式。 大端模式所谓的大端模式(Big-endian)指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。 小端模式所谓的小端模式(Little-endian),指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。 内存中存储的区别: 以32bit的int型数据0x11223344为例,来说明大小端的区别:
大端 11 22 33 44 小端 44 33 22 11 内存地址 0x0000 0x0001 0x0002 0x0003
可见大小端只是针对16bit,32bit,64bit这些占用多于一个字节的数据类型,字节流不存在大小端问题。 大小端的使用情况目前Intel的x86系列芯片是唯一还在坚持使用小端的芯片,ARM芯片默认采用小端,但可以切换为大端;而MIPS等芯片要么采用全部大端的方式储存,要么提供选项支持大端——可以在大小端之间切换。另外,对于大小端的处理也和编译器的实现有关,Java是平台无关的,默认是大端。在网络上传输数据普遍采用的都是大端模式。
可以看出,大小端只是在不同平台间进行数据交换是时候有用。如果在同一个平台下,不管数据在内存中实际是如何表示的,不会影响程序对数据的解释,也就是不用考虑大小端的问题。只有在网络传输时,因为会涉及到不同的平台,才需要考虑大小端的问题。一般情况下,网络上传输数据采用的都是大端模式,如不考虑大小端模式,有可能把一个整型的0x1234做为0x3412处理,导致程序异常。因此,在网络编程时就引入了主机字节序和网络字节序相互转换的函数。 系统字节序转换函数系统标准定义的转换函数有4个: htonl()--"Hostto Network Long int" 32bit ntohl()--"Networkto Host Long int" 32 bit htons()--"Hostto Network Short int" 16 bit ntohs()--"Networkto Host Short int" 16 bit
在Linux系统下的头文件及函数定义: #include uint32_t htonl(uint32_t hostlong); uint16_t htons(uint16_t hostshort); uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort);
在Windows系统的头文件及函数定义: #include u_short PASCAL FAR ntohs( u_short netshort); u_long PASCAL FAR ntohl( u_long netlong); u_short PASCAL FAR htons( u_short hostshort); u_long PASCAL FAR htonl( u_long hostlong);
扩展的64bit long类型的大小端转换函数 static inline int isBigEndian(void) //测试主机大小端 { union { int32_t i; char c[4]; }u; u.i = 1; return (u.c[0] == 0); }
#define swab64(x) \ ((uint64_t)(\ (((uint64_t)(x)& (uint64_t)0x00000000000000ffULL) 24) | \ (((uint64_t)(x)& (uint64_t)0x00ff000000000000ULL) >> 40) | \ (((uint64_t)(x)& (uint64_t)0xff00000000000000ULL) >> 56) ))
uint64_t htonll(uint64_t x) { if (isBigEndian()) { return x; }else { return swab64(x); }
}
uint64_t ntohll(uint64_t x) { return htonll(x); } 对float类型的转换 系统函数和扩展的函数都是针对整型的数据类型。对于浮点数,如果也想使用这些函数,需要做些额外的工作。下面以64bit的double类型为例,来说明使用方法。
doubleinputData64; 假设inputData64是从网络端获取的double类型的数据,下面的代码把正确字节序的double类型的数据保存在data64中。 uint8_t * pData = (uint8_t *) & inputData64; uint64_t tmp_64; doubledata64; tmp_64 = ntohll(*((uint64_t *)pData)); memcpy(&data64, &tmp_64, sizeof (uint64_t)); |
CopyRight 2018-2019 实验室设备网 版权所有 |