关于大端(Big Endian)模式下的struct字节存储顺序(建议在大端模式机器下有过实际开发经验的进)

zenny_chen 2008-03-02 12:17:39
比如:(32位机器下)


#include <stdio.h>

union Test
{
struct
{
unsigned short a;
unsigned short b; // 当然,以上两句我可以写成unsigned short a, b;但是这样更显眼一些:)
}pack;

unsigned int c;
};

int main(void)
{
union Test t = { 0x1234, 0x5678 };

printf("The answer is: 0x%x\n", t.c);

return 1;
}



虽然我已经知道对于一个基本类型的数据,比如int类型在大端模式下将是按照低字节放在高地址上,但是对于结构来说,第一个数据成员将放在高地址还是低地址?
即结果是0x78563412还是0x34127856,或是其它情况?在小端机器上,结果我想大家一定都知道:0x56781234。
...全文
644 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
wfy_serend 2010-02-01
  • 打赏
  • 举报
回复
应该是0x12345678
hoohag 2008-03-02
  • 打赏
  • 举报
回复
struct
{
unsigned short a;
unsigned short b; // 当然,以上两句我可以写成unsigned short a, b;但是这样更显眼一些:)
}pack;

对于你的结构, 比如你用大端的平台去读用小端平台生成的数据. 其数据都是相同的结构类型. 假如数据保存在


buffer BYTE* pBuffer = new BYTE[sizeof(pack)];

那么你的结构 pack sResult = *((pack*)pBuffer) ;
把数据读出来后, 还要相应的高低字节颠倒, 即:
sResult .a = cvt_end(pack.a);
sResult .b = cvt_end(pack.b);
这样你就可以通过结构获得正确的数据
arong1234 2008-03-02
  • 打赏
  • 举报
回复
用htonl
hoohag 2008-03-02
  • 打赏
  • 举报
回复
对于结构不变的, 只是对数据类型相关. 即WORD(双字节)型数据,你要大小尾转换你要高低字节颠倒. 对于DWORD() (4字节)你要先两个WORD间颠倒, 然后两个WORD再各自颠倒
下面是小端转大端的两个宏定义

WORD型:
#define cvt_end2(s) (((s<<8) & 0xFF00) | ((s>>8) & 0xFF))

DWORD型:
#define cvt_end4(s) (((s<<24) & 0xFF000000) | ((s<<8) & 0xFF0000) | \
((s>>8) & 0xFF00) | ((s>>24) & 0xFF))
zenny_chen 2008-03-02
  • 打赏
  • 举报
回复
其实,由于VC++系列不支持C99标准,使得我的一些比较好的代码自动生成方案无法实施。如果没有编译器不支持C99标准,那么要对

union Test
{
struct
{
unsigned short a;
unsigned short b;
}pack;

unsigned int c;
};

这个类型数据的数组进行初始化将变得非常麻烦。因为代码生成依赖于用户参数的输入,对于不同参数,实际初始化的成员是不同的。在C99中可以用:

union Test list1[] = { {.pack.a = 10, .pack.b = 20 }, {.pack.a = 100, .pack.b = 200} };
union Test list2[] = { {.c = 2334}, {.c = 10000} };

以上代码进行初始化。如果没有这种initializer的话,那么初始化union Test就只能对匿名结构进行初始化,而要初始化c时只能通过匿名结构,拆成两个16位的数据组合起来。因此这就关系到大端小端的问题了。

我下载了Wind River编译环境,一看这个界面,用的更本就是Eclipse的东西嘛。其中,使用PowerPC系列作为目标处理器的话就可以看到大端的情况了,结果与Oversense说的一样:0x12345678。而在小端的话则是0x56781234,所以两者结果值是不一样的,正好是两个16位字前后颠倒。

现在已经是凌晨了,所以不能说明天晚上,而是今天晚上准备结贴。后面发表意见的朋友也有得分的机会。
这个Wind River配置起来也比较麻烦,特别是要支持C99还要自己输入命令行-Xlibc-new,如果有个选项选择不是更方便吗?嗨!-_-
不过能够亲眼目睹结果还是比较安心的。

最后还是希望有更多的C/C++编译器能够支持C99。尤其是微软。这次微软的Visual C++2008居然只支持了C99中不定参数的宏定义,加入了__VA_ARGS__,而对于数组、结构、联合的初始化列表特性一点都没有予以支持,太令人失望了。可以以临时变量或参数作为临时数组变量的下标这个特性不支持也就算了。但是上面几个着实为开发带来很大方便,尤其是在嵌入式开发领域。有了这个特性,上面的两个list可以在加载时初始化,而不必等到运行时在做。而且再向用户提供一个专门初始化表的接口函数也确实不太礼貌,而且这些表在目前的实际运用中都是const的,也就是说放在ROM中都完全可以。所以这样就更不能采用初始化函数进行竹椅初始化了。希望Visual Studio可以考虑这个问题。不过考虑到他们已经对VC/C++逐步淡化了,也就不放什么大的希望。
hoohag 2008-03-02
  • 打赏
  • 举报
回复
对于union Test t = { 0x1234, 0x5678 };
t.c在小端平台上输出应该是78563412, 即两个WORD颠倒, 再WORD中各自高低字节颠倒. 这个可以找个solaris的平台试试
cmail 2008-03-02
  • 打赏
  • 举报
回复
结构中成员的声明顺序是不会变的,第一个成员放在低地址。
Oversense 2008-03-02
  • 打赏
  • 举报
回复
0x12345678

64,849

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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