strlen遇上小端模式
在写UDP客户端测试程序的时候,遇到了一个问题,然后百思不得其解,研究了一下午,豁然开朗。
首先看一下遇到的问题
ConnProto conn; conn.type = 1; conn.srcuserid = 110; UserContent node; sprintf(node.strName,"%s","aaaaaa"); sprintf(node.strPassword,"%s","123456"); char buf[1024]; memset(buf,0,sizeof(buf)); char *pData = buf; ConnProto *pConn = (ConnProto*)pData; *pConn = conn; pData += sizeof(ConnProto); UserContent *pNode = (UserContent*)pData; *pNode = node;
sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&servaddr,len);
可是接收端显示只接受到1个字节大小,怎么可能啊。我明明发了两个结构体大小啊(38字节)。
struct ChatContent { int destuserid; char strContent[200]; }; struct UserContent { char strName[20]; char strPassword[10]; };
将sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&servaddr,len);改成
sendto(sockfd,buf,sizeof(ConnProto)+sizeof(UserContent),0,(struct sockaddr*)&servaddr,len);
就可以了,接收端提示收到38个字节。
思考:为甚呢??/
我们知道strlen函数遇到 '\0' 就不向后了。那么这个 strlen(buf)是怎么等于1的呢??
原来,在内存中,先是存储 conn.type = 1;
在内存中就是
高地址 -------------->低地址
0000 0000 0000 0001 (4字节)
0对应的ASCII码就是空字符 '\0'
根据strlen(buf)=1 ,我们猜想 是不是跟大小端有关系呢??(当然当时我是没有这么机智的,还是憋了好久才想到。这里为了简化我木讷的脑袋思考过程)
于是,将 conn.type = 1;改为conn.type = 0;
显示 strlen(buf)=0.
哎呀,变了,那么说明改到了对的地方。接着将onn.type = 0x0x7fffffff;
显示 strlen(buf) = 5。
怎么是5了,不是应该是4吗??别忘了后面还有conn.srcuserid = 110;
这更加证实了 这跟大小端存储有关。
记不得Linux是大端还是小端存储了,没关系,我们测试一下。
#include <stdio.h> #include <stdlib.h> int main() { union { short a; char c; }u; u.a = 0x1234; printf("%d\n",u.c); }
输出:
52
哦,是小端。证实了猜想。
接着为了方便,conn.type = 65; 65对应ASCII码的 A
printf("%d\n",strlen(buf));
printf("%s\n",buf);
输出;
1
A
哦哦,原来在内存中,大家都是以二进制存储的,管你是什么类型,char还是ConnPoto结构体。在以%s的格式打印出就是 A .信不信还能让他输出65.
printf("%d\n",strlen(buf));
printf("%d\n",*buf);
输出;
1
65
看吧。
今天又学到一点。记住一切东西在内存中都是 二进制01存储的,因为我们的输出格式不同才导致结果不同。以后不要畏惧不同格式了。

浙公网安备 33010602011771号