奇怪的little/big endian问题,请大家发言

mimepp 2005-06-21 12:36:42
进来看帖子的朋友都帮着up一下,让帖子别沉了.

问题描述:
从网络上某window XP的PC上收到一串内容 buffer, 表示为16进制如下: (共11 bytes)
00 b9 0b ,01 00 00 00, 00 04 00 00
----->
内存中看到的内容如上,从左往右是内存地址增加方向.
现在有个指针指向 "01" 的位置. 用char *data表示.
这个data的内容是要赋值给一个结构的.
struct test
{
int a;
int b;
};

void fun(char *data, int datalen)
{
struct test *t = (struct test*)data; //data指向"01"所在的地方.
printf("result, a: 0x%08x, b: 0x%08x\n", t->a, t->b);
printf("result, a: %d, b: %d\n", t->a, t->b);
}
传进去的 datalen = 8;

得到的结果应该是
result, a: 0x00000001, b: 0x00000400
result, a: 1, b: 1024

也就是说,我要得到"01"后面, 每4个字节的内容到一个int中.

但实际运行的结果却不是如此. 实际的结果是:
result, a: 0x010bb900, b: 0x00000000
result, a: 17545472, b: 0

即我本来想得到的数据应该为"01" 后面的内容,但实际的结果却是走到了"01"左边的几个字节上.
b的内容也变成了"01" 后面的"00"的那4个字节.

以上的代码是运行在某ARM开发板上的结果.
开发板上sizeof(int)是 4
即4个字节表示一个整数.
sizeof(struct test)为8
data的指针point为0x09...87, 后面的两位为87. 中间的没记下.

后来经过改写:
struct test tmp;
memcpy( &tmp, data, sizeof(sturct test));
printf("result, a: 0x%08x, b: 0x%08x\n", tmp->a, tmp->b);
printf("result, a: %d, b: %d\n", tmp->a, tmp->b);
使用memcpy 来复制内存内容后,结果输出正确. memcpy应该是把data右边的内容copy正确到了tmp中.问题最后是解决了的.


疑问:
1. 有人说不是little/big endian的问题,是数据结构struct test对齐的问题. 大家什么意见?
说是从"data的指针point为0x09...87, 后面的两位为87." 看出的问题. 不被4整除? 好像不是这样吧.大家聊聊自己的看法.
2. 错误出现时, 取到的结果是
a: 01 0b b9 00
b: 00 00 00 00
也就是在字串被这样处理了
00 b9 0b 01, 00 00 00 00, 04 00 00
即data指向的"01"被当成了高位.低位在它的左边. 即得到的是"01"加上它左边的3个字符,而不是右边的3个字符.
不知是否这样解释?
但这个解释好像很奇怪喔. 怎么跑到了左边?

3. 一般大家讨论的情况可能只会涉及到
01 00 00 00, 00 04 00 00
这个的排列的内容的含义:
如:
一种排列为:
01 00 00 00
00 04 00 00
另一种排列为:
00 00 00 01
00 00 04 00

但我这里遇到的是实际运行系统中的现象. 和这个讨论有点不同.
请大家就我的实际例子来讨论.
4. 难道是内存中数据被其他的代码"踩到", 出错了?
5. 不知道代码中其他地方还有没有这样的后患.呵呵.

相关知识,来自网络:
1. Big-Endian 和 Little-Endian 翻译为: 大端,小端
2. Big-Endian 和 Little-Endian
这两个术语来自于 Jonathan Swift 的《《格利佛游记》其中交战的两个派别无法就应该从哪一端--小端还是大端--打开一个半熟的鸡蛋达成一致。:)
在那个时代,Swift是在讽刺英国和法国之间的持续冲突,Danny Cohen,一位网络协议的早期开创者,第一次使用这两个术语来指代字节顺序,后来这个术语被广泛接纳了
摘自《深入理解计算机系统》
3. 含义:
big endian:最高字节在地址最低位,最低字节在地址最高位,依次排列。
little endian:最低字节在最低位,最高字节在最高位,反序排列。
没记错的话,除了moto的68K系列和dec的sparc是big endian外,常见的cpu都是little endian。ARM同时支持big和little,实际应用中通常使用little endian。

欢迎大家讨论.
进来看帖子的朋友都帮着up一下,让帖子别沉了.
...全文
212 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
samsun2000 2005-06-21
  • 打赏
  • 举报
回复
不是很清楚,up

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧