C 语言位域

2025年3月17日 | 阅读 3 分钟

在 C 语言中,我们有 union (联合体) 和 struct (结构体) 数据类型,可以用来声明用户自定义的数据类型。结构体的大小取决于其数据成员。但有时,我们并不需要如此大的数据类型,因为它会占用内存,造成内存浪费。

示例 1

输出

Bit Fields in C

说明

在上面的例子中,我们有一个结构体数据类型,它有三个整型数据成员:date(日)、month(月)和 year(年)。这个数据类型将表示出生日期,三个整数会占用 12 字节的内存。但我们并不需要用这么大的内存来存储这些值,因为我们知道日期的最大值是 31,月份的最大值是 12,而年份可以是最大的位数。

所以我们使用位域来节省内存。在位域中,我们可以以位为单位明确地指定数据成员的宽度或范围。

语法

示例 2

输出

Bit Fields in C

说明

在上面的代码中,我们在结构体变量中使用了位域,因为我们知道 day 变量的最大值是 31,可以用 5 个比特位来表示,所以我们强制使用了 5 作为宽度。

同样地,month 部分最大只需要 12 个值,所以我们可以用最多 4 个比特位来表示(4 个比特位最大可以表示的值是 15)。

对于 year,我们使用了 12 个比特位作为其宽度。

然后我们计算了整个结构体变量所占用的内存,得到的结果是 4 字节,而最初是 12 字节。所以,借助位域,我们节省了 8 字节的内存。

注意:如果我们给一个数据成员指定的宽度超过了其类型的实际范围,那么将会产生编译错误。

示例 3

输出

Bit Fields in C

说明

在上面的代码中,我们有一个字符数据类型,通常占用 1 字节或 8 个比特位。但在位域部分,我们给了它 12 个比特位的宽度,这超出了它的范围,将会导致编译错误。

注意:我们不能在数组中使用位域的概念。

示例 4

输出

Bit Fields in C

说明

在上面的例子中,我们有一个整型数组作为结构体的数据成员,并对其应用了位域,因此我们得到了编译错误。

注意:我们可以使用宽度为 0 的无名数据成员来实现内存对齐,将后续的数据成员分配到下一个内存边界之后。

示例 5

输出

Bit Fields in C

说明

在上面的代码中,我们有一个字符成员,然后是一个宽度为 0 的无名整型成员。因此,我们会跳过到下一个4字节对齐的地址,然后下一个字符数据成员将占用那里的内存。

注意:如果我们使用位域,就无法获取数据成员的地址。

示例 6

输出

Bit Fields in C

说明

如果我们试图获取位域数据成员的地址,就会得到一个错误。