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

[复制链接]
 楼主| 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的语法
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中编译后最后一条语句没有编译结果(无反汇编语句),请帮忙解释一下好不?
聆风 发表于 2009-8-26 08:56 | 显示全部楼层
unTEST unTest;
         unsigned char i;
         unTest.stTest.bLOW4 = 0x0F;
         unTest.stTest.bHigh4 = 0x06;
         i = unTest.bTest;
改成以上看看. 你书写有错误无法编译通过
ruiwei0201 发表于 2009-8-26 10:16 | 显示全部楼层
我书写错误是我手动往这里敲的,编译肯定是不会报错的。。。我已经能调试了,你想编译会有错误吗
 楼主| xnwxq 发表于 2009-8-26 12:57 | 显示全部楼层
同意2楼的说法,最好还是使用与或的位操作比较安全
yxwsz 发表于 2009-8-26 14:32 | 显示全部楼层
bit field顺序和endian有关;
winloop 发表于 2009-8-26 16:44 | 显示全部楼层
对齐方式决定的,比较古老的问题了
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编译器上还是多少
聆风 发表于 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

粉丝
快速回复 在线客服 返回列表 返回顶部