有些时候,根据一个数据的取值范围(主要看最大取值),其在存储时并不需要占用一个完整的字节,只需要占用一个或几个二进制位即可。例如开关只有通电和断电两种状态,用0和1表示足以,也就是用一个二进位。为了节省存储空间,并使处理简便,C/C++语言又提供了一种数据结构,叫做“位域”或“位段”。位域的定义和位域变量的说明位域定义与结构定义相仿。
struct 位域结构名 { 位域列表 };
其中位域列表的形式为: 类型说明符 位域名:位域长度。
比如,我们想用一个struct来表示年-月-日,由于我们知道月份的取值范围是1-12,用4bit就可以表示;日的取值范围是1-31,用5bit就可以表示。这样我们就可以这样来定义struct Data_1,只需要占用4byte就可以存储。
struct Data_1 // sizeof(Data_1) = 4
{
unsigned int year :23;
unsigned int month :4; //range: 1-12
unsigned int day :5; //range: 1-31
};
再比如,有8个开关量,可以用位域来表示。
struct TEST_1 // sizeof(TEST_1) = 1
{
bool a:1;
bool b:1;
bool c:1;
bool d:1;
bool e:1;
bool f:1;
bool g:1;
bool h:1;
};
关于位域的使用,有以下几个规则:
- 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。
- 位域的长度不能大于数据类型本身的长度,比如int类型就不能超过32位。
- 不能对位域进行 取地址操作
- 可以直接对位域进行赋值,但要注意赋的值不要超过位域的最大值范围,否则会出现溢出,如果cout,得到的是截断后的值。
关于使用位域时,内存对齐及存储大小,有以下规则。
- 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止
- 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
- 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++,GCC采取压缩方式;
- 如果位域字段之间穿插着非位域字段,则不进行压缩;
- 整个结构体的总大小为最宽基本类型成员大小的整数倍。数据对齐,请参考我之前的博客https://blog.csdn.net/zgcjaxj/article/details/105929486
参考 https://blog.csdn.net/sty124578/article/details/79456405
#include <iostream>
using namespace std;
struct Data
{
unsigned int year ;
unsigned char month;
unsigned char day;
};
struct Data_1
{
unsigned int year :23;
unsigned int month :4; //range: 1-12
unsigned int day :5; //range: 1-31
};
struct TEST
{
bool a;
bool b;
bool c;
bool d;
bool e;
bool f;
bool g;
bool h;
};
struct TEST_1
{
bool a:1;
bool b:1;
bool c:1;
bool d:1;
bool e:1;
bool f:1;
bool g:1;
bool h:1;
};
struct pack
{
unsigned a:12; // unsigned int,省略了int
unsigned :20;//该位域成员不能使用,用于填充
unsigned c:6;
};
int main(int argc, char** argv)
{
cout<< "sizeof Data = "<<sizeof(Data)<<endl;
cout<< "sizeof Data_1 = "<<sizeof(Data_1)<<endl;
cout<< "sizeof TEST = "<<sizeof(TEST)<<endl;
cout<< "sizeof TEST_1 = "<<sizeof(TEST_1)<<endl;
pack t_1;
t_1.c = 100; // 7'b1100100, exceed 6bit,overflow, will truncate
cout<< "sizeof pack = "<<sizeof(pack)<<endl;
cout<< "t_1.c = "<<dec<<t_1.c<<endl;
return 0;
}
result :
sizeof Data = 8
sizeof Data_1 = 4
sizeof TEST = 8
sizeof TEST_1 = 1
sizeof pack = 8
t_1.c = 36