结构体拾遗补缺2:结构体的位域(位段)

原创 2013年12月02日 22:06:21

一、位域的定义

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

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

位结构定义的一般形式为: 
struct  位结构名{ 
    数据类型 [变量名]: 整型常数;   //成员称为“位域”或者“位段”
    数据类型 [变量名]: 整型常数; 
} 位结构变量;

其中: 数据类型必须是整型(包括字符型)。 整型常数的范围是数据类型的长度, 如定义为short,则范围是1~16,也就是说,当定义一个short类型的成员位段时,它的整形常数取值范围必须在0-16之间,超出范围编译器将报语法错。具体范围如下:

类型 整形常数范围
char, unsigned char 1-8
short, unsigned short 1-16
int, unsigned 1-32
long, unsigned long 1-32

当然上面的范围值也可以是0,但是作用不同,后面会提到。


例如:

struct webpage{ 
    unsigned char incon: 8;      // incon占用低字节的0~7共8位
    unsigned char txcolor: 4;   // txcolor占用高字节的0~3位共4位
    unsigned char bgcolor: 3;  // bgcolor占用高字节的4~6位共3位
    unsigned char blink: 1;      // blink占用高字节的第7位
}ch;
printf("%d\n", sizeof(struct webpage));

输出结果:2。

 

2. 位域的对齐与计算

上面结构体大小为2,但是,为什么会是2呢?因为结构体必须要遵守对其原则(前面已经讲过),另外,位域也要遵守下面3个对齐原则

1). 若相邻位域变量的类型相同,且其位宽之和 不大于 变量类型宽度(在此严重强调,是类型位宽而不是成员变量sizeof,也不是类型的sizeof或者其他什么)大小,则:后面的变量将紧邻前一个变量存储,直到不能容纳为止;

    struct A

    {

        char a : 2;

        char b : 3;

        char c : 1;

    }

    ,该结构体占1个字节。
2). 如果相邻位域变量的类型相同,但其位宽之和 大于 变量类型宽度大小,则后面的成员将从新的存储单元开始,其偏移量为其类型大小的整数倍;

    struct B

    {

        char a : 3;

        char b : 4;

        char c : 2;

    }

    ,该结构体占2个字节。
3). 如果相邻的位域变量的类型不同,不同位域变量存放在不同的位域类型字节中(这一条其实会根据编译器的不同而采用不同的规则)。

例如:

    struct C
    {
        char a : 1;
        char b : 3;
        short c : 13;
        int d : 3;
    };

    ,该结构体占8个字节。

    总结,在组织位域各变量时,步骤如下:

    1)首先根据它们的变量类型(必须是整型char、short、int、long),遵循结构体的对齐原则,分配各类型的空间;

    2)然后,在每个类型内部,根据各变量的位长,遵循位域的对齐原则,进行分段。

 

    如果位域上的整形范围值是0,则下个位域从新的字节开始(即使是同类型的位域),如:

    struct bs
    {
        int a : 4;
        int : 0;      // 空域
        int b : 4;    // 从新字节开始存放
        int c : 4;
    } ;

    上面这个位域定义中,a占第一字节的4位,后4位填0表示不使用;b从新的字节(下一个int)开始,占用4位,c占用4位。上面位结构体占8个字节。

 

3. 位域的访问

    结构体的位域变量的访问与普通的结构体变量的访问相同。 例如: 访问下例位结构中的bgcolor成员可写成ch.bgcolor 进行访问: 
    struct A

    { 
        char a : 8;      
        char b : 4;   
        char c : 3;  
        char d : 1;      
    }m;

    访问结构体中的b,代码为:m.b;

    位域变量可以没有位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:

    struct k
    {
        int a:1;
        int :2;    // 该2位不能使用
        int b:3;
        int c:2;
    };

    结构体的位域变量可以与其它普通的结构体变量一起使用,例如:
    struct A

    { 
        char name[8]; 
        int age; 
        char state : 1; 
        char pay : 1; 
    }workers;

相关文章推荐

(转)C结构体之位域(位段)

转载自C结构体之位域(位段)有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便...
  • lc013
  • lc013
  • 2016年10月02日 10:49
  • 210

结构体、位段(位域)详解

结构体大小前边简单介绍了一下,现在对计算结构体的大小进行详细的解释,希望能帮助大家。...

结构体之位域(位段)

有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构...

C结构体之位域(位段)

有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构...

全面总结sizeof的用法(定义、语法、指针变量、数组、结构体、类、联合体、位域位段)

一、前言 编译环境是vs2010(32位)。 #include     #include     #include using namespace std; typedef struct {     ...

c 结构体之位域(位段)

有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构...

C 结构体之位域(位段) | C Bit Fields

概述 有些信息在存储时,并不需要占用一个完整的字节,而只需占用几个或一个二进制位。 例如在存放一个开关量时,只有 0 和 1 两种状态,用一位二进位即可。 为了节省存储空间,并使处理简便,C 语言又提...

(必看)C结构体与C结构体之位域(位段)的sizeof问题.

C结构体总结(自己总结) 1.结构体变量的首地址应该是结构体大小的整数倍(当结构体大小大于处理器位数(现在一般是64位即8字节)时,应该是处理器位数(字节数)的整数倍) 2.结构体成员相对于结构体...

C语言结构体,位段

1.结构的定义 在实际情况中,数据经常以成组的形式存在。如果这些值的类型各不相同,他们无法同时存储于同一个数组中,在C中,可以使用结构把不同类型的值存储在一起,所以结构也是一些值的集合,这些值称为...
  • hudazhe
  • hudazhe
  • 2017年07月09日 01:33
  • 160

C结构体中位段的使用(http://liouwei20051000285.blog.163.com/blog/static/25236742011124406783/)

C语言: C中的位段的使用 01 /* 02         DATE : 2010.6.24 03         关于C中的位端igned或者int 04 */ 05 #includ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:结构体拾遗补缺2:结构体的位域(位段)
举报原因:
原因补充:

(最多只允许输入30个字)