1.首先回忆结构体
我们都知道定义一个结构体可以这样的方式定义:
- struct Point {
- float x;
- float y;
- } point; //等价于: struct Point point;
除此之外,如果不想声明结构体,只想定义结构体的话,还可以这样:
- struct {
- float x;
- float y;
- } point; //等价于: struct Point point;
2.位域之简单应用
做低层时,经常会读写寄存器,比如操作某位,设置为0或1,而在C语言中便为我们提供一种数据结构”位域”,使得我们通过读写”位域”来实现操作某位.
例如一个常见的位域的结构体,操作如下所示:
- #include <stdio.h>
-
- struct {
- unsigned mode:8; //bit[0,7]:模式选择
- unsigned en:1; //bit[8] :使能选择
- unsigned reserved:1; //bit[9] :保留reserved (也可以写成unsigned reserved:1;)
- unsigned clk_select:4; //bit[10,13]:时钟选择
- unsigned ch_select:3; //bit[14,15]:通道选择
- }reg11; //定义一个reg11变量,不声明结构体的好处在于确保变量唯一性
-
- int main()
- {
- reg11.en =1; //bit8=1 --> 256
- printf("reg11=%d\n",reg11); //打印 256
- reg11.mode =50;
- printf("reg11=%d\n",reg11); //打印 256+50
- return 0;
- }
打印:

3.位域之越界处理
比如,我们定义的某个位域只有固定1位,如果向该位写入超过1位的值.会自动保留最低1位.
示例:
- #include <stdio.h>
- struct {
- unsigned mode:8; //bit[0,7]:模式选择
- unsigned en:1; //bit[8] :使能选择
- unsigned reserved:1; //bit[9] :保留reserved(也可以写成unsigned reserved:1;)
- unsigned clk_select:4; //bit[10,13]:时钟选择
- unsigned ch_select:3; //bit[14,15]:通道选择
- }reg11; //定义一个reg11变量,不声明结构体的好处在于确保变量唯一性
-
- int main()
- {
- reg11.en =1; //bit8=1 --> 256
- printf("1st:reg11=%d\n",reg11); //打印 256
- reg11.en =5; //5(b'101) 保留低1位: b'1
- printf("2st:reg11=%d\n",reg11); //打印 256
- reg11.en =6; //5(b'110) 保留低1位: b'0
- printf("3st:reg11=%d\n",reg11); //打印 0
-
- return 0;
- }
打印:

4.注意, 使用位域的结构体的长度默认最小值为int型(4字节),如果超过4字节(32位),则会是64位
示例:
- #include <stdio.h>
-
- struct {
- unsigned a:4;
- unsigned b:2;
- unsigned c:1;
- }reg1; //位域总长度只有7位
- struct reg{
- unsigned a:4;
- unsigned b:2;
- unsigned c:32;
- }reg2;
- int main()
- {
- printf("%d\n",sizeof(reg1));
- printf("%d\n",sizeof(reg2));
- return 0;
- }
打印:

5.如果某个寄存器只有8位(1字节),该如何使用位域处理?
使用union联合体,使各字段共享一块内存,通过读写union结构体里的char变量即可.
示例:
- #include <stdio.h>
- typedef union{
- unsigned char val;
- struct {
- unsigned a:4;
- unsigned b:1;
- unsigned c:2;
- unsigned d:1;
- }bit;
- }reg11; //使用typedef ,告诉编译器,reg11是个声明类型
-
- int main()
- {
- reg11 reg;
- printf("sizeof=%d\n",sizeof(reg.val));
- reg.val=0;
- reg.bit.b = 1; //bit[4]=1
- printf("val = %d\n",reg.val);
- return 0;
- }
打印:
