C语言中位域

1.位域的定义
        C语言中位域也叫位段,经常在STM32或DSP固件库中应用。ANSI C标准中规定,有下面三种数据类型可以用于位域,signed int  和 unsigned int 和_Bool。

struct 
{
   unsigned int a:1;
   unsigned int b:2;
   unsigned int c:1;
}abc;

        上面声明建立了2个1位的字段,1个2位的字段。abc.a或c可以赋值为0或1,而abc.b可以赋值为0~3,因为它占两位。:冒号后面的数字用来限定成员变量占用的位数。

2. 位域的宽度

        位域宽度不能超过它所依附的数据类型长度,比如上面冒号后面数字不能超过int占用位数,32位环境中int占32位,所以上述声明冒号后面数字都不能超过32.

 3. 位域的存储

        上述例子中结构体只占用4个字节(考虑对齐),假如下面的声明:

struct 
{
   unsigned int a:2;
   unsigned int b:1;
   unsigned int c:31;
}abc;

        上述声明abc.c占用31位,abc.b占用1,abc.a占用2位,但是结构体总共占用8个字节空间。其中abc.a占用前面4个字节,abc.c和b占用后面4个字节,如有描述错误,欢迎指正~~~

4. 无名位域

struct 
{
   unsigned int a:2 ;
   unsigned int :18 ;
   unsigned int c:16;
}abc;

        上面声明中,如果没有位宽为18的无名成员,a和c将挨着存储共占用4个字节。有了18的无名成员作为填充,a和c将分开存储,结构体占8个字节,前4个字节存a和无名成员,后四个字节存c,无名成员不能使用。所以无名位域主要用于调整成员存储位置或填充内存。

5. 位的应用

     下面是某MCU固件库对寄存器的封装,所有寄存器都被封装为联合体类型,联合体里面有一个32位的成员和一个结构,该结构以位域的形式体现,这样操作某些寄存器的位就比较方便了。

         unon GPIOA_REG  uGPIOAREG;

        比如要操作GPIOA的bit4-7位为0101,uGPIOAREG.bit.GPIO1=5即可,如果要把整个寄存器写1,只需要操作uGPIOAREG.all = 0xffff;即可。

        除开上面应用外,还可以使用联合体结合位域的方式管理一些状态量,如果一个程序中有很多状态量要管理的话。

 

猜你喜欢

转载自blog.csdn.net/fengel_cs/article/details/120646897
今日推荐