现在的位置: 首页 > 综合 > 正文

C语言位域总结

2014年01月02日 ⁄ 综合 ⁄ 共 1930字 ⁄ 字号 评论关闭

一、前言 
    有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。
二、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:
        struct 位域结构名 
        { 位域列表 };
其中位域列表的形式为: 类型说明符 位域名:位域长度
例如: 
struct sa 

char a:3; 
char b:4; 
char c:1; 
};

三、位域的内存分配
1) 若相邻成员变量类型相同,且其位宽之和不大于成员变量类型位宽(在此严重强调,是 类型位宽 而不是成员变量sizeof,也不是类型的sizeof或者其他什么)大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止; 
2) 如果相邻位域字段的类型相同,但其位宽之和不大于成员变量的类型宽度大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍; 
3) 如果相邻的位域字段的类型不同,不同位域字段存放在不同的位域类型字节中;(这一条其实会根据编译器的不同而采用不同的规则,此处以VC++6.0标准来说明)
 看了些网上的资料和C关于位域的书籍,然后动手在编译器上测试,发现网上和书上的关于位域内存分配的内容和我的测试结果有偏差(姑且认为那些内容是错误的);包括前言对位域的说明也不够严谨!
(1) 位域必须存放在一个字节里面,不能跨越两个字节;(这句有误) 
例如: 
struct s 

   short a:5; 
   short b:5; 
   short c:5; 
}sa; 
在TC2.0/VC6.0/gcc上sizeof(sa)得到的大小一致为2; 可见,位域可以跨越两个字节,位域可以跨越sizeof(定义位域的类型)个字节!如上例可以跨越sizeof(short)=2个字节。 
(2) 位域的长度不能大于1个字节,即不能大于8;(这句也有误) 
例如: 
struct s 

   short a:9; 
   short b:3; 
   short c:4; 
}sa; 
同样,在TC2.0/VC6.0/gcc上编译通过,且sizeof(sa) = 2;因此同1,位域的长度大小应该是不超过8*sizeof(定义为域的类型) 
(3) 关于空域 
struct s 

   short a:5; 
   short :0;    //空域 
   short b:5; 
}sa; 
测试结果:sizeof(sa) = 4;空域后面的位域从新的存储单元开始;一个存储单元包括sizeof(定义位域的类型)个字节; 
(4) 关于无名域 
struct s 

   short a:5 
   short :5; //无名域 
   short c:5; 
}sa; 
在VC6.0/GCC上测试结果:sizeof(sa) = 2;填充5位,总位数小于16,所以大小为2。 
注:把无名域也看成是位域;因此它也必须满足(1)和(2)。
四、位域的使用 
    对于位域的使用,同其他结构体成员使用一样;如可以这样引用上面定义的位域:s.a ; s.c ;空域和无名域不可访问!对位域赋值不能超过位域所能表示的最大范围,超过了将会被截短。
struct bs
{
unsigned a:1;
unsigned b:3;
unsigned c:4;
} bit,*pbit;
main()
{
bit.a=1;
bit.b=7;
bit.c=15;
printf("%d,%d,%d\n",bit.a,bit.b,bit.c);
pbit=&bit;
pbit->a=0;
pbit->b&=3;
pbit->c|=1;
printf("%d,%d,%d\n",pbit->a,pbit->b,pbit->c);

上例程序中定义了位域结构bs,三个位域为a,b,c。说明了bs类型的变量bit和指向bs类型的指针变量pbit。这表示位域也是可以使用指针的。程序的9、10、11三行分别给三个位域赋值。( 应注意赋值不能超过该位域的允许范围)程序第12行以整型量格式输出三个域的内容。第13行把位域变量bit的地址送给指针变量pbit。第14行用指针方式给位域a重新赋值,赋为0。第15行使用了复合的位运算符"&=", 该行相当于: pbit->b=pbit->b&3位域b中原有值为7,与3作按位与运算的结果为3(111&011=011,十进制值为3)。同样,程序第16行中使用了复合位运算"|=",
相当于: pbit->c=pbit->c|1其结果为15。程序第17行用指针方式输出了这三个域的值。

抱歉!评论已关闭.