请澄清我对C字段和联盟的理解

时间:2016-02-10 06:03:59

标签: c cpu-registers unions bit-fields

我正在查看微控制器驱动程序文件,并且无法理解正确使用联合和位字段

typedef union
{
     uint8 U;                          //Unsigned 
     sint8 I;                          //signed 
     Register_x_Bits B;                //Bit field access 
}u1;

typedef struct _Register_x_Bits        //8 bit register size 
{
    uint8 Field1:1;                    //endianness is maintained for all registers      
    uint8 Field2:1;                
    uint8 Field3:1;                    
    uint8 Field4:1;                   
    uint8 Field5:4;    
}Register_x_Bits;


u1 reg;

reg.U = ReadRegister();                 // data is initially being read from the register 

//based on the previous data  a bit value needs to be changed in particular location of the data 

reg.B.Field3 = 0;

WriteRegister(reg.U);

这是我无法理解的地方

1)通过仅改变reg.B.Field3位字段值,它是否只改变一个特定位(在这种情况下为字段3)或者清除寄存器中的所有先前数据并用新的{{填充它1}}

许多教程都声明reg.B.Field3

中只有一个活跃成员

2)我可以在同一个寄存器中更改多个位字段吗? 我可以通过上述相同的方法更改它们并保持其余完整

Unions

编辑 enter image description here

让整个寄存器值为reg.B.Field1 =0; reg.B.Field3 =1; reg.B.Field4 =1100; ,现在如果我更改1111 0 1 0 1会影响Fields 1,3,4中的值吗?

2 个答案:

答案 0 :(得分:1)

好的,请先检查下面的代码

#include <stdio.h>
typedef struct _BITS{
    unsigned char f1:1;
    unsigned char f2:1;
    unsigned char f3:1;
    unsigned char f4:1;
    unsigned char f5:4;

}BITS;
typedef union {
    unsigned char a;
    char b;
    BITS c;
}u1;

int main(void) {
    u1 reg;
    reg.a = 255;
    reg.c.f1 = 0;
    //reg.c.f2 = 1;
    printf("%d", reg.c.f1);
    printf("%d", reg.c.f2);
    return 0;
}

为了模仿ReadRegister(),我写了reg.a = 255。所以现在当我写reg.c.f1 = 0并且它正在改变所有位时,reg.c.f2也会打印0。但它不会发生。 Bitfield仅针对该特定位,而不是整个字节。因此不,它只会清除那个位

现在,如果我写reg.a = 0reg.c.f1 = 255,如果它设置了所有位,那么reg.c.f2将产生1但不会。因此不能你不能设置位字段的所有位

修改 但是你可以用其他方式设置多个位。参见@sdao的答案

希望能回答你的问题

答案 1 :(得分:0)

1:您可以单独更改字段而不影响其他字段 2:您可以同时更改多个字段。

仅供参考:在您的情况下,可以将值设置为每个字段[0: sizeof(unsigned char)],但每个字段可以接收的实际值取决于它的位数,因此请小心
假设您有 N 位字段,则将 M 分配给该字段,然后将设置的实际值为:(M & (N^2 - 1))其中{{1}是面具。

例如:

(N^2 - 1)