一。 最近在做嵌入式系统**与windows的网络通信,由于**这边要发送的数据有char,float,int型,这些类型在内存中的存放格式不一样,所以我选择定义结构体进行处理!
如下:
struct data { char AA[8]; float BB[4]; int CC[4]; char DD[6];
}sendBuf;
|
可是这样定义就出现了一个问题,VC对变量存储会有一个特殊处理。为了提高CPU的存储速度,VC对一些变量的起始地址做了“对齐”处理。在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。所以这个结构体用sizeof()以后会得出:48。详见:所以当我用网络发送结构体:
send(socket,(struct data*)&sendBuf,sizeof(sendBuf),0)
|
发送后,接收端我用char buf[]接收。可是当我要进行小端数据转换时却得不到正确的数据,并且出现多余字节。本来这只需要48个字节就可以接收完,可是,却到了50,那么中间的一些字节是哪里来的呢?我现在还想不通!正是因为这样,产生了错位,我没法找到正确的float型数据在内存中的二进制存储起始地址,那就没法对它进行数据转换,那么相应也就不能进行数据处理了!
在网上找了很久,却没发现满意的答案!好多都是如何发送结构体的,其实发送结构体就是上面的那条语句。后来突然想起来上面的struct的字节长度,才有所悟,觉得是不是我应该对它进行一个自我补全呢?想想干脆把结构体定义成如下:
struct data { char AA[8]; float BB[4]; int CC[4]; char DD[8];
}sendBuf;
|
这样我先把char DD[]中多的两个字节置0,对数据处理也没多大影响,这下再发送,接收到的数据竟然居然真的正常了。我再进行数据转换,位置也就直接按照数据存储格式所占的空间稍微计算一下就得出起始位置了。关于这个问题,我也想不通为什么。
二。接下来就是windows端的数据处理了
首先我接收到的数据存入一个文件里。由于数据很多,我不可能只定义一个buf就能把数据装下。所以就只有定义一个小buf,每次从文件里读取一些数据出来。这样就有一个问题,我们需要找到上一次读完数据的地址。于是我决定用fseek()函数。
模拟测试代码如下:
/********************************************************** * fptest.c * introduce:假设我是每8个数据为1帧,并且每100个数据存放在FLASH * 的一块地址里,由些算来100个数据里就只有完整的8*12=96 * 个数据,余下的四个数据为0,也就是无效数据。如果我们 * 每次只从文档里读取8个数据,这样的话最后帧就会断开,也 * 会给数据处理带来一些麻烦。所以我选择每次从文档里读出 * 100个数据。这样我可以直接对前面的96个处理,余下的不管 * date: 2009-05-05 name: dongfs **************************************************************/ #include "stdio.h" #include "string.h"
void main() { FILE *fp;/*定义文件型指针变量*/
int i,j,k;
char writeBuf[900];/*模拟要存入文档的大量数据*/ char readBuf[100];/*每次要读出来的数据*/
/*初始化buf,它所需的头文件为string.h*/ memset(readBuf,'\0',sizeof(readBuf));
/*初始化writeBuf*/ for (k = 0; k < 9; k++) { for (i = 0; i < 100; i++) { writeBuf[i+k*100] = i; } } /*打开文件,"wb+"为读写建立一个新的二进制文件*/ if ((fp = fopen("data.txt","wb+")) == NULL) { perror("open error!\n"); } /*将数据块writeBuf写入文档*/ if (fwrite(writeBuf,900,1,fp) == NULL) { perror("write error!\n"); } else fclose(fp);
/*打开文件:为读写打开一个二进制文件*/ if ((fp = fopen("data.txt","rb+")) == NULL) { perror("open error!\n"); }
printf("\n"); /*循环读取100次,将文档的数据依次读完*/ for (i = 0; i < 100; i++) { /*由于要对文件进行顺序读写,那么就要找到控制文件的位置指针。
用fseek函数可以实现改变文件的位置指针。但是fseek()函数
一般用于二进制文件,因为文本文件要发生字符转换,计算位置时 往往会发生混乱。所以在我读写前的参数都是使用的二进制参数。*/ fseek(fp,i*100,0); fread(readBuf,100,1,fp);
for (j = 0; j < 100; j++) { printf("readBuf[%d] = %d\n",j,readBuf[j]); }
printf("\n"); printf("\n"); }
fclose(fp); }
|
三.以上均为我学习时的一些总结,很基础,希望大家不要笑哈!
阅读(5938) | 评论(3) | 转发(2) |