C语言中的位域



当我们声明一个结构体或联合体类型时,结构体/联合体类型变量的大小取决于其各个元素的大小。您可以设置位的大小来限制大小,而不是使用默认的内存大小。指定的大小称为位域

这是声明位域的语法

struct {
   data_type elem : width;
};

假设您的 C 程序包含许多在名为status的结构体中分组的 TRUE/FALSE 变量,如下所示:

struct {
   unsigned int widthValidated;
   unsigned int heightValidated;
} status;

此结构体需要 8 字节的内存空间,但实际上,我们每个变量都只存储“0”或“1”。C 语言提供了一种更好的方法来利用此类情况下的内存空间。

如果您在结构体中使用此类变量,则可以定义变量的宽度,这告诉 C 编译器您只打算使用那么多字节。例如,上述结构体可以改写如下:

struct {
   unsigned int widthValidated : 1;
   unsigned int heightValidated : 1;
} status;

上述结构体需要 4 字节的内存空间来存储status变量,但只使用 2 位来存储值。

示例

如果您最多使用 32 个变量,每个变量的宽度为 1 位,那么status结构体也将使用 4 个字节。但是,一旦您有 33 个变量,它将分配下一个内存槽,并将开始使用 8 个字节。

让我们检查以下示例以了解这个概念:

#include <stdio.h>

/* define simple structure */
struct {
   unsigned int widthValidated;
   unsigned int heightValidated;
} status1;

/* define a structure with bit fields */
struct {
   unsigned int widthValidated : 1;
   unsigned int heightValidated : 1;
} status2;

int main() {

   printf("Memory size occupied by status1: %d\n", sizeof(status1));
   printf("Memory size occupied by status2: %d\n", sizeof(status2));
   
   return 0;
}

输出

编译并执行上述代码后,将产生以下输出:

Memory size occupied by status1: 8
Memory size occupied by status2: 4

位域声明

位域的声明在结构体内部具有以下形式:

struct {
   type [member_name] : width ;
};

下表描述了位域的变量元素:

元素 描述
类型

一个整数类型,它决定如何解释位域的值。

类型可以是int、signed intunsigned int

成员名称 位域的名称。
宽度 位域中的位数。“宽度”必须小于或等于指定类型的位宽。

使用预定义宽度定义的变量称为位域。位域可以容纳多个位;例如,如果您需要一个变量来存储 0 到 7 的值,则可以定义一个宽度为 3 位的位域,如下所示:

struct {
   unsigned int age : 3;
} Age;

上述结构体定义指示 C 编译器变量“Age”将仅使用 3 位来存储值。如果您尝试使用超过 3 位,则它将不允许您这样做。

示例

让我们尝试以下示例:

#include <stdio.h>

struct {
   unsigned int age : 3;
} Age;

int main() {

   Age.age = 4;
   printf("Sizeof(Age): %d\n", sizeof(Age));
   printf("Age.age: %d\n", Age.age);

   Age.age = 7;
   printf("Age.age : %d\n", Age.age);

   Age.age = 8;
   printf("Age.age : %d\n", Age.age);

   return 0;
}

输出

编译上述代码时,将出现警告:

warning: unsigned conversion from 'int' to 'unsigned char:3' changes value from '8' to '0' [-Woverflow]|

执行时,将产生以下输出:

Sizeof(Age): 4
Age.age: 4
Age.age: 7
Age.age: 0

您可以在存储空间有限的情况下使用位域。当设备传输编码到多个位中的状态或信息时,位域也很有效。每当某些加密程序需要访问字节内的位时,都使用位域来定义数据结构。

广告