C++ 结构体位域

为了节省存储空间,并使处理简便,C/C++ 又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几 个不同的区域,并说明每个区域的位数。每个域有一个域名,可以在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。结构体中的位域(bit field)是一种特殊的成员变量,它可以用来表示更小的内存单元(按位存储),从而节省内存空间。

1、定义声明

位段成员必须声明为intunsigned intsigned int类型(shortchar long)。位域的定义和位域变量的说明位域定义与结构定义类似,其形式为:

struct 位域结构名
{ 位域列表 };

其中位域列表的形式为:

类型说明符 位域名:位域长度

例如,

struct packed_struct {
   unsigned int f1:1;
   unsigned int f2:1;
   unsigned int f3:1;
   unsigned int f4:1;
   unsigned int type:4;
   unsigned int my_int:9;
}

也可以这样定义:

struct packed_struct {
   unsigned int f1:1;
   unsigned int f2:1;
   unsigned int f3:1;
   unsigned int f4:1;
   unsigned int type:4;
   unsigned int my_int:9;
} pack;

使用示例如下:

#include <iostream>
using namespace std;

struct BitField {
    unsigned int a : 3; // 占用 3 位
    unsigned int b : 5; // 占用 5 位
    unsigned int c : 2; // 占用 2 位
};

int main() {
    BitField bf;

    bf.a = 5;  // 5 的二进制是 101,符合 3 位
    bf.b = 31; // 31 的二进制是 11111,符合 5 位
    bf.c = 3;  // 3 的二进制是 11,符合 2 位

    cout << "a = " << bf.a << endl;
    cout << "b = " << bf.b << endl;
    cout << "c = " << bf.c << endl;

    return 0;
}

2、位域的作用及存储规则

使用位域的主要作用是压缩存储,其大致规则为:

1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止

2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;

3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++,GCC采取压缩方式;

4) 如果位域字段之间穿插着非位域字段,则不进行压缩;

5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。

3、使用示例

位域是一种轻量级、紧凑的存储机制,适合嵌入式系统和高性能需求的应用,但需要注意跨平台兼容性和赋值范围限制。对于普通应用程序,除非对内存优化有特殊需求,否则更推荐使用常规成员变量。

1)控制寄存器字段

#include <iostream>
using namespace std;

struct ControlRegister {
    unsigned int enable : 1;  // 第 0 位: 启用
    unsigned int mode   : 3;  // 第 1-3 位: 模式
    unsigned int status : 4;  // 第 4-7 位: 状态
};

int main() {
    ControlRegister reg;

    reg.enable = 1; // 启用
    reg.mode = 5;   // 模式设为 5 (101)
    reg.status = 9; // 状态设为 9 (1001)

    cout << "Enable: " << reg.enable << endl;
    cout << "Mode: " << reg.mode << endl;
    cout << "Status: " << reg.status << endl;

    return 0;
}

2)查看位域的大小

#include <iostream>
using namespace std;

struct BitField {
    unsigned int a : 3; // 3 位
    unsigned int b : 5; // 5 位
    unsigned int c : 2; // 2 位
};

int main() {
    cout << "Size of BitField: " << sizeof(BitField) << " bytes" << endl;
    return 0;
}

推荐阅读
cjavapy编程之路首页