C语言结构体之位域

时间:2021-10-30 10:47:12

有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。

例如:

struct p
{
  int a:8;
  int b:2;
  int c:6;
}data;
在内存中即:

高位 0000 |0000 00|00|0000 0000|  低位

                       c         b          a

这里有几点需要说明:

1.位域的大小不能超过所定义的数据类型,比如int是32位,若定义int a:33则编译器会报错error C2034:“p::a”:位域类型对位数太小

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

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

4.如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式(不同位域字段存放在不同的位域类型字节中),Dev-C++和GCC都采取压缩方式;

下面举一些例子来佐证:

struct p
{
  char a:7;
  char b:2;
  char c:6;
}data;

高位 0000 |0000 00|00 0|000 0000|  低位 (a占去了8bit中的7bit,剩下的1bit放不下b,所以b放入新的单元)

                       c         b          a

struct p{
short a:7;
short b:2;
short c:6;
}data;

此时情况则不同,因为short型有16位,abc都可以放下

高位 0000 |0000 00|00 |0000 0000|  低位

                       c         b          a

struct p{
short a:7;
char b:2;
char c:6;
}data;
在VC中,即使b可以放在a的后面,但它们的数据类型不一样,故b需要放入新单元

高位0000 00|00| 0000 0000 0|000 0000|  低位

               c      b                              a