#include <stdio.h>
/* 定义简单的结构 */
struct
{
unsigned int widthValidated;
unsigned int heightValidated;
} status1;
/* 定义位域结构 */
struct
{
unsigned int widthValidated : 12;
unsigned int heightValidated : 21;
} 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 : 12
Memory size occupied by status2 : 8
位段,C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或称“位域”( bit field) 。利用位段能够用较少的位数存储数据。来自百度百科
下面是一些规则:
规定,位域的宽度不能超过它所依附的数据类型的长度。通俗地讲,成员变量都是有类型的,这个类型限制了成员变量的最大长度,: 后面的数字不能超过这个长度。
如果将heightValidated的位数改为了33,就会超出int的最大位数4X8=32,
程序会报错:
位域的大小无效
/* 定义位域结构 */
struct
{
unsigned int widthValidated : 12;
unsigned int heightValidated : 33;
} status2;
规定,只有有限的几种数据类型可以用于位域。在 ANSI C 中,这几种数据类型是 int、signed int 和 unsigned int(int 默认就是 signed int);到了 C99,_Bool 也被支持了。
规定, 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止。若其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
status1的大小是4,因为12+20=32,没有超出int的最大长度
status2的大小是8,因为12+21=33,超出int的最大长度
/* 定义位域结构 */
struct
{
unsigned int widthValidated : 12;
unsigned int heightValidated : 20;
} status1;
/* 定义位域结构 */
struct
{
unsigned int widthValidated : 12;
unsigned int heightValidated : 21;
} status2;
规定,如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6,VS2019采取不压缩方式,Dev-C++,GCC采取压缩方式;
在VS中执行得到:Memory size occupied by status2 : 8
在Linux下GCC中执行得到:Memory size occupied by status2 : 4
struct
{
unsigned int widthValidated : 12;
bool heightValidated : 1;
} status2;
规定,整个结构体的总大小为最宽基本类型成员大小的整数倍。
规定,如果位域字段之间穿插着非位域字段,则不进行压缩;
struct
{
unsigned int widthValidated : 12;
double heightValidated ;
unsigned int widthValidated1 : 14;
} status2;