• 【程序员面试宝典读书笔记】位域


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

    一、位域定义与结构定义相仿,其形式为:

    struct 位域结构名

    {

         位域列表

    };

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

    例如:

    struct bs
    {
       int a:8;
       int b:2;
       int c:6;
    };

    二、位域的几点说明:

    1、一个位域必须存储在同一个存储单元中,不能跨两个单元。如果某存储单元空间中不能容纳下一个位域,则该空间不用,而从下一个存储单元起存放该位段。例如:

    struct as
    {
        unsigned a:4;
        unsigned b:29;//从下一单元开始存放
    };

    所以sizeof(as)=8;

    struct bs
    {
        unsigned a:4;
        unsigned b:27;
    };

    所以sizeof(bs)=4;

    2、位域的长度不能大于数据类型本身的长度,比如int类型就能超过32位二进位,char类型就不能超过8位二进位。例如:

    struct bs
    {
        unsigned a:4;
        unsigned b:33;//出错
    };

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

    struct bs
    {
        unsigned a:4;
        unsigned :3;//无名位域,不能使用
        unsigned b:5;
    };

    三、位域的对齐(摘自百度百科)

    如果结构体中含有位域(bit-field),那么VC中准则是:

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

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

    3、如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式(不同位域字段存放在不同的位域类型字节中),Dev-C++和GCC都采取压缩方式:系统会先为结构体成员按照对齐方式分配空间和填塞(padding),然后对变量进行位域操作。

    四、举例

    #include <iostream>
    using namespace std;
    
    typedef struct A
    {
            unsigned a:4;
            unsigned b:2;
            unsigned c:20; //当没有占满一个存储单元时,结构体的大小对齐为一个存储单元的大小
            unsigned d:7; //前面已经为26,故7+26>33已超过一个存储单元,所以7在一个新的存储单元存放
            unsigned e:28;//由于前面的7在一个新的存储单元的开头存放,且28+7>32, 故在另一个新的存储单元存放
            unsigned :3;//可以定义无名位段,此例中该无名位段占用3位的空间,该空间将不被使用       
    };                  //由于前面的28在一个新的存储单元的开头存放,且28+3<32, 故不用在另一个新的存储单元存放
                         //所以最后求出的A的大小是4 + 4 + 4 =12
    typedef struct B
    {
            unsigned a:4;
            unsigned b:2;
            unsigned c:20;
            unsigned d:6;
            //unsigned i:1;当多出此行时,该结构体大小由4变为8,因为此行之前正好为32位
    };
    
    typedef struct C
    {
            unsigned a:4;
            unsigned b:2;
            unsigned :0;    //定义长度为0的位段时不能指定名字,否则编译不过
            unsigned c:1;   //定义了0字段后,紧接着的下一个成员从下一个存储单元开始存放;
    };                      //此例子中,c前面那个存储单元中的余下的26位中被0填充了
                           //所以最后求出的A的大小是4 + 4 = 8
    
    int main()
    {
            A a; B b;C c;
            cout<<"sizeof(a)="<<sizeof(A)<<endl;
            cout<<"sizeof(b)="<<sizeof(b)<<endl;
            cout<<"sizeof(c)="<<sizeof(c)<<endl;
            system("pause");
            return 0;
    }
    

    运行结果:



     

  • 相关阅读:
    io学习三
    io学习二
    io学习一
    多线程学习(十五)
    spring源码阅读(四)
    多线程学习(十四)
    多线程学习(十三)
    设计模式(一)
    spring源码阅读(三)
    spring源码阅读(二)
  • 原文地址:https://www.cnblogs.com/ruan875417/p/4495584.html
Copyright © 2020-2023  润新知