从NSData转double
// .h中
FOUNDATION_EXPORT double floatFromData(NSData *data);
// .m中
double floatFromData(NSData *data) {
char* pData = data.bytes;
char pData2[8] = {0};
for (int i = 0; i < 8; i++)
{
pData2[i] = pData[7 - i];
}
double val = 0;
memcpy(&val, pData2, 8);
return val;
}
从double转NSData
typedef union{
double f;
char c[8];
}DOUBLE_CONV;
/************************************************************
Conversion little endian float data to big endian
*************************************************************/
static double __ltobf(double data)
{
DOUBLE_CONV d1, d2;
d1.f = data;
d2.c[0] = d1.c[7];
d2.c[1] = d1.c[6];
d2.c[2] = d1.c[5];
d2.c[3] = d1.c[4];
d2.c[4] = d1.c[3];
d2.c[5] = d1.c[2];
d2.c[6] = d1.c[1];
d2.c[7] = d1.c[0];
return d2.f;
}
涉及的知识点一::
首先了解到C语言中的各个数据类型的大小是由编译器位数所决定的!!!
一般情况下:
32位编译器:
char short int long float double 指针
1 2 4 4 4 8 4
64位编译器:
char short int long float double 指针
1 2 4 8 4 8 8
涉及的知识点二::
字节序的问题
字节序分为大端字节序和小端字节序
- 大端字节序是指一个整数的高位字节(32-31bit)存储在内存的低地址处,低位字节(0-7bit)存储在内存的高地址处。
- 小端字节序是指一个整数的高位字节(32-31bit)存储在内存的高地址处,低位字节(0-7bit)存储在内存的低地址处。
现代PC大多采用小端字节序,所以小端字节序又被称为主机字节序。
大端字节序也称为网络字节序。
即使是同一台机器上的两个进程(比如一个由C语言,另一个由Java编写)通信,也要考虑字节序的问题(JVM采用大端字节序)。
可编写 byteorder.cpp 判断机器字节序
void byteorder()
{
union
{
short value;
char union_bytes[sizeof(short)];
}test;
test.value = 0x0102;
if (sizeof(short) == 2)
{
if (test.union_bytes[0] == 1 && test.union_bytes[1] == 2)
cout << "big endian" << endl;
else if (test.union_bytes[0] == 2 && test.union_bytes[1] == 1)
cout << "little endian" << endl;
else
cout << "unknown" << endl;
}
else
{
cout << "sizeof(short) == " << sizeof(short) << endl;
}
return ;
}
判断字节序
可以通过下面的小程序测试自己的机器是大端字节序还是小端字节序
#include <stdio.h>
union
{
char ch;
int i;
}un;
int main(void)
{
un.i = 0x12345678;
if(un.ch == 0x12)
{
printf("big endian\n");
}
else
{
printf("small endain\n");
}
return 0;
在测试程序中,使用联合体的原因是:union型数据所占的空间等于其最大的成员所占的空间。对union型成员的存取都是相对于该联合体基地址的偏移量为0处开始,也就是联合体的访问不论对哪个变量的存取都是从union的首地址开始的。通过检测第一个字节存放的数据即可得出结果。
网络字节序
网络上传输的数据都是字节流,对于一个多字节数值,在进行网络传输的时候,先传递哪个字节?也就是说,当接收端收到第一个字节的时候,它将这个字节作为高位字节还是低位字节处理,是一个比较有意义的问题;
UDP/TCP/IP协议规定:把接收到的第一个字节当作高位字节看待,这就要求发送端发送的第一个字节是高位字节;而在发送端发送数据时,发送的第一个字节是该数值在内存中的起始地址处对应的那个字节,也就是说,该数值在内存中的起始地址处对应的那个字节就是要发送的第一个高位字节(即:高位字节存放在低地址处);由此可见,多字节数值在发送之前,在内存中因该是以大端法存放的;
所以说,网络字节序是大端字节序;
在实际中,当在两个存储方式不同的主机上传输时,需要借助字节序转换函数。
字节序转换函数
#include <arpa/inet.h>
// 将主机字节序转换为网络字节序
unit32_t htonl (unit32_t hostlong);
unit16_t htons (unit16_t hostshort);
// 将网络字节序转换为主机字节序
unit32_t ntohl (unit32_t netlong);
unit16_t ntohs (unit16_t netshort);
// 说明:h -----host;n----network ;s------short;l----long。
例如:
#include <stdio.h>
#include <arpa/inet.h>
int main()
{
unsigned int x = 0x12345678;
unsigned char *p = (unsigned char *)&x;
printf("%0x_%0x_%0x_%0x\n",p[0],p[1],p[2],p[3]);
unsigned int y = htonl(x);
p = (unsigned char*)&y;
printf("%0x_%0x_%0x_%0x\n",p[0],p[1],p[2],p[3]);
return 0;
}
主机字节序(小端) 78_56_34_12
低位字节 0x78 位于低位地址p
高位字节0x12 位于高位地址p+3
网络字节序(大端)12_34_56_78