打印

关于C结构体bit field的跨平台的教训

[复制链接]
2386|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xnwxq|  楼主 | 2009-8-23 19:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
ST, TE, TEST, AC, mac
C语言的STRUCT提供了一种叫bit field的语法,可以根据需要决定成员占用某字节的从X位到Y位,例如,下面一个结构:
struct tagtest
{
   char a:4;
   char b:2;
   char c:2;
};

这个定义的含义是整个结构是一个字节长度,成员a占4位,b占2位,c占2位。这样定义以后,我们可以方便的通过设置成员的值来设置结构,而不需要进行位操作了。例如:
tagtest myTest;
myTest.a = 10;
myTest.b = 2;
myTest.c = 1;

但今天发现一个问题,就是windows系统上的和MAC上对待这个结构是不同的;现象如下:
如果在windows上这是上面的值,在MAC上得到的结构成员值为:
myTest.a = 6;myTest.b = 2;myTest.c = 2;
仔细分析之后觉得这个不是字节序的问题,因为字节序对一个字节是不起作用的,如果起作用那传输数据就麻烦了了;那么是什么问题导致的呢?
应该是编译器造成的,规律如下:
在WINDOS上,编译器认为c是字节的高位,而a是字节的低位;但MAC上正好相反了;a 是字节的低位,c是字节的低位。
紧记在心!!!
评分
参与人数 1威望 +4 收起 理由
香水城 + 4

相关帖子

沙发
香水城| | 2009-8-23 21:56 | 只看该作者
最好还是使用与或的位操作比较安全。

使用特权

评论回复
板凳
ruiwei0201| | 2009-8-24 17:10 | 只看该作者
ADS中貌似不能这样操作...?

使用特权

评论回复
地板
聆风| | 2009-8-25 13:32 | 只看该作者
ADS支持bit field的语法

使用特权

评论回复
5
ruiwei0201| | 2009-8-25 16:15 | 只看该作者
本帖最后由 ruiwei0201 于 2009-8-25 16:21 编辑

回LS: 下面是我测试代码:
      typedef union _tagTEST{
                    struct{
                    unsigned char bLOW4 : 4;
                    unsigned char bHigh4 : 4;
                    }stTest;
                    unsigned char bTest;
         }unTEST;
         unTEST unTest;
         unsigned char i;
         unTest.stTest.bLow4 = 0x0F;
         stTest.stTest.bHigh4 = 0x06;
         i = unTest.bTest;
我在ADS中编译后最后一条语句没有编译结果(无反汇编语句),请帮忙解释一下好不?

使用特权

评论回复
6
聆风| | 2009-8-26 08:56 | 只看该作者
unTEST unTest;
         unsigned char i;
         unTest.stTest.bLOW4 = 0x0F;
         unTest.stTest.bHigh4 = 0x06;
         i = unTest.bTest;
改成以上看看. 你书写有错误无法编译通过

使用特权

评论回复
7
ruiwei0201| | 2009-8-26 10:16 | 只看该作者
我书写错误是我手动往这里敲的,编译肯定是不会报错的。。。我已经能调试了,你想编译会有错误吗

使用特权

评论回复
8
xnwxq|  楼主 | 2009-8-26 12:57 | 只看该作者
同意2楼的说法,最好还是使用与或的位操作比较安全

使用特权

评论回复
9
yxwsz| | 2009-8-26 14:32 | 只看该作者
bit field顺序和endian有关;

使用特权

评论回复
10
winloop| | 2009-8-26 16:44 | 只看该作者
对齐方式决定的,比较古老的问题了

使用特权

评论回复
11
nimme| | 2009-8-26 17:02 | 只看该作者
看了一楼的东东,觉得奇怪。位域是和endian有关,但是不明白的是,你在window下如下操作
myTest.a = 10;
myTest.b = 2;
myTest.c = 1;
然后再读出来它得值应该还是10,2,1,
你在MAC下如下操作
myTest.a = 10;
myTest.b = 2;
myTest.c = 1;
然后再读出来它得值应该还是10,2,1,
我不明白你的意思,你在误导大家。我觉得不管在什么编译器环境。你对位域变量赋值后,再读位域变量的值,应该是不变得在A编译器上是多少,在B编译器上还是多少

使用特权

评论回复
12
聆风| | 2009-8-26 17:37 | 只看该作者
1. 注意对齐问题. ADS下如:
typedef __packed struct
{
    unsigned char bLength;
    unsigned char bDescriptorType;
    unsigned short wTotalLength;
    unsigned char bNumInterfaces;
    unsigned char bConfigurationValue;
    unsigned char iConfiguration;
    unsigned char bmAttributes;
    unsigned char MaxPower;
} USB_config_desc_t;
2. ADS下的位结构肯定没问题. 俺用过N遍. N>10.
3. 不同的编译器. 同样的数据结构出来的结果有可能不一样.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:我们都是风雨中的孩子,手牵着手才不会跌倒

162

主题

294

帖子

1

粉丝