搜索
bottom↓
回复: 18

[求助]GCC中有什么办法修改位段的对齐方式?

[复制链接]

出0入296汤圆

发表于 2008-7-18 03:02:31 | 显示全部楼层 |阅读模式
例如,有一个位端,
typedef struct BYTE_BIT
{
    unsigned BIT0:1;
    unsigned BIT1:1;
    unsigned BIT2:1;
    unsigned BIT3:1;
    unsigned BIT4:1;
    unsigned BIT5:1;
    unsigned BIT6:1;
    unsigned BIT7:1;
}BYTEBIT;

GCC中,当我用这个位段来修改变量时
unsigned char chValue = 0x00;

(*(BYTEBIT *)(&chValue)).BIT0 = 1;
最后得到的结果却是0x80。
显然,说明GCC中,位段的对齐方式不是
Bitfields are packed right to left.
而是
Bitfields are packed left to right.
的。
GCC中有没有什么方法修改这种对齐方式呢?

谢谢指教。

出0入0汤圆

发表于 2008-7-18 04:33:26 | 显示全部楼层
应该不是GCC的问题。

(原文件名:CAP13.jpg)

出0入0汤圆

发表于 2008-7-18 08:09:12 | 显示全部楼层
Gorgon Meducer 傻孩子 (印象中最顽固的ICC派)
终于是肯用GCC了。

出0入296汤圆

 楼主| 发表于 2008-7-18 10:45:01 | 显示全部楼层
因为 AVR32 目前只有GCC 可以用……

出0入0汤圆

发表于 2008-7-18 11:25:09 | 显示全部楼层
代码例子:
#include <avr/io.h>

typedef struct BYTE_BIT
{
    unsigned BIT0:1;
    unsigned BIT1:1;
    unsigned BIT2:1;
    unsigned BIT3:1;
    unsigned BIT4:1;
    unsigned BIT5:1;
    unsigned BIT6:1;
    unsigned BIT7:1;
}BYTEBIT;

int main(void)
{
        unsigned char chValue = 0x00;
        unsigned char i=0;

        DDRA=0xFF;

        for(i=0;i<10;i++)
        {

                (*(BYTEBIT *)(&chValue)).BIT0 = 1;

                chValue=chValue+PINA;

                PORTA=chValue;
        }
        return(TRUE);
}

汇编成机器指令(部分代码):
17:               unsigned char chValue = 0x00;
+00000053:   8219        STD     Y+1,R1           Store indirect with displacement
20:               DDRA=0xFF;
+00000054:   EF8F        SER     R24              Set Register
+00000055:   BB8A        OUT     0x1A,R24         Out to I/O location
+00000056:   E020        LDI     R18,0x00         Load immediate
25:                       (*(BYTEBIT *)(&chValue)).BIT0 = 1;
+00000057:   8199        LDD     R25,Y+1          Load indirect with displacement
+00000058:   6091        ORI     R25,0x01         Logical OR with immediate
+00000059:   8399        STD     Y+1,R25          Store indirect with displacement
27:                       chValue=chValue+PINA;
+0000005A:   B389        IN      R24,0x19         In from I/O location
+0000005B:   0F89        ADD     R24,R25          Add without carry
+0000005C:   8389        STD     Y+1,R24          Store indirect with displacement
29:                       PORTA=chValue;
+0000005D:   BB8B        OUT     0x1B,R24         Out to I/O location
22:               for(i=0;i<10;i++)
+0000005E:   5F2F        SUBI    R18,0xFF         Subtract immediate
+0000005F:   302A        CPI     R18,0x0A         Compare with immediate
+00000060:   F7B1        BRNE    PC-0x09          Branch if not equal
32:       }

+00000058使用了逻辑或,操作很正常啊!

出0入0汤圆

发表于 2008-7-18 11:44:37 | 显示全部楼层
5楼我回的帖子怎么没了。

强烈欢迎傻孩子大人进入GCC阵营。
GCC的最大优点就是标准,通用。
GCC使用者遍布全世界各个角落。

我测试也没问题,不过建议字节位域用:
typedef struct
{  
    unsigned char BIT0:1;  
    unsigned char BIT1:1;  
    unsigned char BIT2:1;  
    unsigned char BIT3:1;  
    unsigned char BIT4:1;  
    unsigned char BIT5:1;  
    unsigned char BIT6:1;  
    unsigned char BIT7:1;  
}BYTEBIT;

出0入296汤圆

 楼主| 发表于 2008-7-18 11:53:35 | 显示全部楼层
强烈建议大家在AVR32 Studio中测试这个问题……

出0入0汤圆

发表于 2008-7-18 12:06:00 | 显示全部楼层
楼上试试 sizeof(BYTE_BIT)等于多少?
在IAR里:
typedef struct  
{   
    unsigned  BIT0:1;   
    unsigned  BIT1:1;   
    unsigned  BIT2:1;   
    unsigned  BIT3:1;   
    unsigned  BIT4:1;   
    unsigned  BIT5:1;   
    unsigned  BIT6:1;   
    unsigned  BIT7:1;   
}BYTEBIT;

sizeof(BYTEBIT)=sizeof(int)

出0入296汤圆

 楼主| 发表于 2008-7-18 12:20:07 | 显示全部楼层
to 【7楼】 ATmega32 上官金虹
   那是字节对齐导致的,你把代码修改为以下方式再看看?

#pragma pack(1)
typedef struct   
{   
    unsigned  BIT0:1;   
    unsigned  BIT1:1;   
    unsigned  BIT2:1;   
    unsigned  BIT3:1;   
    unsigned  BIT4:1;   
    unsigned  BIT5:1;   
    unsigned  BIT6:1;   
    unsigned  BIT7:1;   
}BYTEBIT;
#pragma pack()

出0入0汤圆

发表于 2008-7-18 12:45:56 | 显示全部楼层
还是一样。


struct   
{     
    unsigned  BIT0:1;  
}
可能是占用存储空间是int,也可能是char,与编译器有关。
个人认为显式指定unsigned char BIT0;1更好,这样确保只占用一个字节。
(以上可能有误,关于位域,标准C是如何规定的,还没仔细研究过)

如果BYTEBIT占用空间是int,那么
(*(BYTEBIT *)(&chValue)).BIT0 = 1;
有可能存在问题。

就如
unsigned char  chValue;
*(unsigned int *)&chValue;
是有可能存在问题的。




(原文件名:Image0173.JPG)
哪位高人翻译一下?

出0入0汤圆

发表于 2008-7-18 13:27:00 | 显示全部楼层
嵌入式编程中不推荐使用bit fileds,因为标准里没严格规定,会给移植带来问题。

出0入0汤圆

发表于 2008-7-18 13:39:43 | 显示全部楼层
如果对齐
在 WINGCC 里
struct     
{      
    unsigned  BIT0:1;
        .
        .
        .
} BYTEBIT;
sizeof(BYTEBIT)是2字节;

在AVR32GCC里
sizeof(BYTEBIT)是4字节;

#pragma pack(1)
typedef struct BYTE_BIT
{
    unsigned  BIT0:1;
        .
        .
        .
}BYTEBIT;
#pragma pack()
都为1字节;

avr32 GCC 汇编出来的机器指令为:
        (*(BYTEBIT *)(&chValue)).BIT0 = 1;
0x80000130 <main+28>: sub     r10,r7,2
0x80000134 <main+32>: ld.ub   r8,r10[0x0]
0x80000136 <main+34>: mov     r9,1
0x80000138 <main+36>: bfins   r8,r9,0x7,0x1
0x8000013c <main+40>: st.b    r10[0x0],r8

bfins我就看不懂了。

如图:

(原文件名:1.JPG)

出0入0汤圆

发表于 2008-7-18 22:11:52 | 显示全部楼层
AVR32STUDDIO=Eclipse+GCC
流口水啊。

avr_studio太破烂了,ATMEL什么时候也把AVR_STUDIO换成Eclipse就好了。

出0入0汤圆

发表于 2008-7-20 15:59:23 | 显示全部楼层
傻孩子,问题解决了吗?

bfins    Rd, Rs, o5, w5    Insert the lower w5 bits of Rs in Rd at bit-offset

bfins    r8, r9,0x7,0x1    将r9的低1位插入到r8的第7位,是这样理解的吗?

出0入296汤圆

 楼主| 发表于 2008-7-20 19:31:38 | 显示全部楼层
问题解决了。和GCC版本有关系,对于较高版本,可以通过
#pragma reverse_bitfield或者-mreverse_bitfield来实现
对于低版本,就只能用宏的方法,重新编写一个逆序的位段
来解决了。

出0入296汤圆

 楼主| 发表于 2008-9-2 12:17:09 | 显示全部楼层
整理帖子,自己顶一下……

出0入296汤圆

 楼主| 发表于 2008-9-2 12:18:21 | 显示全部楼层
以下蓝色文字由版主:Gorgon Meducer 于:2008-09-02,12:18:21 加入。
<font color=black>请发贴人注意:
本贴放在这分区不合适,即将移走
原来分区:[9999]AVR (原ourAVR.com) 技术论坛
即将移去的分区:[1038]傻孩子(Gorgon Meducer)专栏
移动执行时间:自本贴发表0小时后

任何的疑问或咨询,请可随时联系站长。谢谢你的支持!
</font>

出0入0汤圆

发表于 2008-9-2 14:25:37 | 显示全部楼层
胡乱写的,不要照抄,按这个意思写就行了.
你的struct里全是位,编译器当然没必要帮你按字节对齐.借助union用一个unsigned char来限制它就行了.

typedef struct BYTE_BIT
{
  union{
    unsigned char byte_data;
    struct bit_data_s{
      unsigned BIT0:1;
      unsigned BIT1:1;
      unsigned BIT2:1;
      unsigned BIT3:1;
      unsigned BIT4:1;
      unsigned BIT5:1;
      unsigned BIT6:1;
      unsigned BIT7:1;
   }bit_data;
}BYTEBIT;


...

BYTEBIT test;

test.bit_data.BIT0 = 1;

出0入0汤圆

发表于 2008-9-2 17:07:06 | 显示全部楼层
学习
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-8 13:58

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表