Gorgon_Meducer 发表于 2008-7-18 03:02:31

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

例如,有一个位端,
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中有没有什么方法修改这种对齐方式呢?

谢谢指教。

testcode 发表于 2008-7-18 04:33:26

应该不是GCC的问题。
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_350851.jpg
(原文件名:CAP13.jpg)

ATmega32 发表于 2008-7-18 08:09:12

Gorgon Meducer 傻孩子 (印象中最顽固的ICC派)
终于是肯用GCC了。

Gorgon_Meducer 发表于 2008-7-18 10:45:01

因为 AVR32 目前只有GCC 可以用……

TTLife 发表于 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使用了逻辑或,操作很正常啊!

ATmega32 发表于 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;

Gorgon_Meducer 发表于 2008-7-18 11:53:35

强烈建议大家在AVR32 Studio中测试这个问题……

ATmega32 发表于 2008-7-18 12:06:00

楼上试试 sizeof(BYTE_BIT)等于多少?
在IAR里:
typedef struct
{   
    unsignedBIT0:1;   
    unsignedBIT1:1;   
    unsignedBIT2:1;   
    unsignedBIT3:1;   
    unsignedBIT4:1;   
    unsignedBIT5:1;   
    unsignedBIT6:1;   
    unsignedBIT7:1;   
}BYTEBIT;

sizeof(BYTEBIT)=sizeof(int)

Gorgon_Meducer 发表于 2008-7-18 12:20:07

to 【7楼】 ATmega32 上官金虹
   那是字节对齐导致的,你把代码修改为以下方式再看看?

#pragma pack(1)
typedef struct   
{   
    unsignedBIT0:1;   
    unsignedBIT1:1;   
    unsignedBIT2:1;   
    unsignedBIT3:1;   
    unsignedBIT4:1;   
    unsignedBIT5:1;   
    unsignedBIT6:1;   
    unsignedBIT7:1;   
}BYTEBIT;
#pragma pack()

ATmega32 发表于 2008-7-18 12:45:56

还是一样。


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

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

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



http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_351310.JPG
(原文件名:Image0173.JPG)
哪位高人翻译一下?

errrre 发表于 2008-7-18 13:27:00

嵌入式编程中不推荐使用bit fileds,因为标准里没严格规定,会给移植带来问题。

TTLife 发表于 2008-7-18 13:39:43

如果对齐
在 WINGCC 里
struct   
{      
    unsignedBIT0:1;
      .
      .
      .
} BYTEBIT;
sizeof(BYTEBIT)是2字节;

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

#pragma pack(1)
typedef struct BYTE_BIT
{
    unsignedBIT0: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
0x80000136 <main+34>: mov   r9,1
0x80000138 <main+36>: bfins   r8,r9,0x7,0x1
0x8000013c <main+40>: st.b    r10,r8

bfins我就看不懂了。

如图:
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_351350.JPG
(原文件名:1.JPG)

ATmega32 发表于 2008-7-18 22:11:52

AVR32STUDDIO=Eclipse+GCC
流口水啊。

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

TTLife 发表于 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位,是这样理解的吗?

Gorgon_Meducer 发表于 2008-7-20 19:31:38

问题解决了。和GCC版本有关系,对于较高版本,可以通过
#pragma reverse_bitfield或者-mreverse_bitfield来实现
对于低版本,就只能用宏的方法,重新编写一个逆序的位段
来解决了。

Gorgon_Meducer 发表于 2008-9-2 12:17:09

整理帖子,自己顶一下……

Gorgon_Meducer 发表于 2008-9-2 12:18:21

以下蓝色文字由版主:Gorgon Meducer 于:2008-09-02,12:18:21 加入。<font color=black>请发贴人注意:本贴放在这分区不合适,即将移走
原来分区:AVR (原ourAVR.com) 技术论坛
即将移去的分区:傻孩子(Gorgon Meducer)专栏
移动执行时间:自本贴发表0小时后
任何的疑问或咨询,请可随时联系站长。谢谢你的支持!</font>

rainyss 发表于 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;

yaogang 发表于 2008-9-2 17:07:06

学习
页: [1]
查看完整版本: [求助]GCC中有什么办法修改位段的对齐方式?