C语言中的位域

 

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

二、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:

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

其中位域列表的形式为: 类型说明符 位域名:位域长度

例如:
struct sa
{
char a:3;
char b:4;
char c:1;
};

三、位域的内存分配

    看了些网上的资料和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 ;空域和无名域不可访问!对位域赋值不能超过位域所能表示的最大范围,超过了将会被截短。

五、位域的效率
    大家都知道,结构体成员的对齐是为了提高访问数据的效率;而位域成员显然没有进行结构体对齐,这样对数据访问的效率存在影响吗?
理所当然(应该是我想当然)这样会降低效率;然而,我看了一些网页上的资料(我没有进行仔细的分析,只是借用别人的结论);对位域成员的访问在编译阶段进行了优化;从生成的汇编源代码看出效率是一样的,并没有降低!

六、结束语
    毕竟本人水平有限,以上内容,个人愚见,如有错误,还望指正...(别让我生在错中不知错,呵呵~~)!

 

 

 

ps:空域的问题

 

struct A{
    unsigned a:4;
    unsigned :0;
    unsigned b:3;
};

struct B{
    unsigned a:4;
    unsigned :32;
    unsigned b:3;
};

sizeof(A)=8 while sizeof(B)=12   gcc

struct A{
    unsigned a:4;
    unsigned :0;
    unsigned b:3;
};

int *p=(int*)&a;
*p=0x80000023;
p=p+1;
*p=0x0000000e;

printf(" %d %d\n",a.a,a.b);

output:3  6

你可能感兴趣的:(C语言中的位域)