0%

C语言 struct的位域

C语言的结构体位域

前面可以看到,使用unoin共用体可以节省数据的存储空间。

同样,在结构体或者共用体中,使用位域也可以达到这个效果。

先看看什么时候可以使用位域,这个特点大多数人都不会用到,用到的大部分人都基本跟底层打交道,比如驱动开发、单片机开发等。

先看一个最简单的例子,比如我们的红绿灯系统,先定义一个结构体:

1
2
3
4
5
6
typedef struct
{
unsigned int red;
unsigned int green;
unsigned int yellow;
} TrafficLight;

此时如果看一下TrafficLight结构体的大小,应该是12个字节

但是我们知道对于这几种灯而言,只有2中状态,开和关,也就是1和0,也就是1个bit其实就能表达,所以针对这种情况,有了位域的概念,先看一下位域的声明:

1
2
3
4
typedef struct 
{
type name : width;
}
  • type:整数类型
  • name:为位域的名称
  • width:为位域中位的数量,其值需要小于等于type指定的类型大小

所以交通灯的结构体使用位域的概念就如下所示:

1
2
3
4
5
6
typedef struct
{
unsigned int red : 1;
unsigned int green : 1;
unsigned int yellow : 1;
} TrafficLight1;

三色红绿灯加起来一共需要3个bit,所以一个无符号整型就可以容纳这些值了,此时看一下这个结构体的长度,应该为4

总结一下:

当结构体或共用体中有无符号整型或有符号整型成员时,C语言允许用户指定这些成员所占用的存储位数,即位域。通过将数据存储在它们所需的最小数目的存储位内,位域能够有效地提供存储空间的利用率,但是,要注意,位域成员必须被声明为有符号整型或无符号整型

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*beginner/struct/struct6.c*/
#include <stdio.h>

int main()
{

typedef struct
{
unsigned int red;
unsigned int green;
unsigned int yellow;
} TrafficLight;

TrafficLight trafficlight;

printf("The size of TrafficLight %d\n", sizeof(trafficlight));

typedef struct
{
unsigned int red : 1;
unsigned int green : 1;
unsigned int yellow : 1;
} TrafficLight1;

TrafficLight1 trafficlight1;

printf("The size of TrafficLight1 %d\n", sizeof(trafficlight1));

return 0;
}

编译运行

直接输入make就可以了。

1
2
3
4
#beginner/struct/Makefile

struct6: struct6.c
gcc -o struct6 struct6.c

运行输出如下:

1
2
3
$ ./struct6
The size of TrafficLight 12
The size of TrafficLight1 4

扩展

既然位域指定了长度位,所以就涉及到万一赋值超过了会发生什么情况,可以通过给红绿灯赋一个大值看看。

比如复制一个2,那么会得到如下警告:

1
warning: implicit truncation from 'int' to bit-field changes value from 2 to 0 [-Wbitfield-constant-conversion]

编译有警告,不过还是生成了可执行文件,运行下看看结果吧。

处无为之事,行不言之教;作而弗始,生而弗有,为而弗恃,功成不居!

欢迎关注我的其它发布渠道