C语言-位域操作

我们在使用单片机时经常会用到某些某些变量来表示某些状态,例如Led_Flag的1或0表示开与关,我们可以定义一个结构体来进行操作:

struct LEDS{
	uchar Led_Green;
	uchar Led_Red;
	uchar Led_Blue;
}leds;

当我们需要控制LED灯开关状态时,只需要:

leds->LED_Green=0/1;

这种方法是可行的,但在大部分时候,某个变量只有两个状态,或者三个等,这样定义了一个八位的变量却只用到了其中的两位,浪费了很多资源,特别对于大部分片上资源紧缺单片机来说,这是需要避免的。因此,除了结构体,C语言还提供了另一种定义方式--位域,位域的定义方式与结构体类似,例子如下:

	struct BITTYPE{
		uchar bit0:1;
		uchar bit1:1;
		uchar bit2:1;
		uchar bit3:1;
		uchar bit4:1;
		uchar bit5:1;
		uchar bit6:1;
		uchar bit7:1;	
	}bittype;

位域与结构体很像,主要形式:

struct 位域结构名 
{

 位域列表

};

其中位域列表结构位:

type [member_name] : width ;

各名称定义为:

元素 描述
type 只能为 int(整型),unsigned int(无符号整型),signed int(有符号整型) 三种类型,决定了如何解释位域的值。
member_name 位域的名称。
width 位域中位的数量。宽度必须小于或等于指定类型的位宽度。

对于位域还有一些需要注意的点:

  • 一个位域存储在同一个字节中,如一个字节所剩空间不够存放另一位域时,则会从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:
struct bs{
    unsigned a:4;
    unsigned  :4;    /* 空域 */
    unsigned b:4;    /* 从下一单元开始存放 */
    unsigned c:4
}

在这个位域定义中,a 占第一字节的 4 位,后 4 位填 0 表示不使用,b 从第二字节开始,占用 4 位,c 占用 4 位。

  • 位域的宽度不能超过它所依附的数据类型的长度,成员变量都是有类型的,这个类型限制了成员变量的最大长度,: 后面的数字不能超过这个长度。

  • 位域可以是无名位域,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:

struct k{
    int a:1;
    int  :2;    /* 该 2 位不能使用 */
    int b:3;
    int c:2;
};

位域的使用与结构体一致

位域变量名.位域名
位域变量名->位域名

实例

#include <stdio.h>
 
int main(){
    struct bs{
        unsigned a:1;
        unsigned b:3;
        unsigned c:4;
    } bit,*pbit;
    bit.a=1;    /* 给位域赋值(应注意赋值不能超过该位域的允许范围) */
    bit.b=7;    /* 给位域赋值(应注意赋值不能超过该位域的允许范围) */
    bit.c=15;    /* 给位域赋值(应注意赋值不能超过该位域的允许范围) */
    printf("%d,%d,%d\n",bit.a,bit.b,bit.c);    /* 以整型量格式输出三个域的内容 */
    pbit=&bit;    /* 把位域变量 bit 的地址送给指针变量 pbit */
    pbit->a=0;    /* 用指针方式给位域 a 重新赋值,赋为 0 */
    pbit->b&=3;    /* 使用了复合的位运算符 "&=",相当于:pbit->b=pbit->b&3,位域 b 中原有值为 7,与 3 作按位与运算的结果为 3(111&011=011,十进制值为 3) */
    pbit->c|=1;    /* 使用了复合位运算符"|=",相当于:pbit->c=pbit->c|1,其结果为 15 */
    printf("%d,%d,%d\n",pbit->a,pbit->b,pbit->c);    /* 用指针方式输出了这三个域的值 */
}
posted @ 2023-03-01 13:54  seekwhale13  阅读(219)  评论(0)    收藏  举报