C位域操作


位域的概念

1個字節包含8位,有些變量保存的數據不需要占用這么長的空間(比如bool類型,只有兩個狀態true和false, 1位就可以搞定,剩下的7位就浪費了),這就催生了“位域”結構,位域將1個字節划分成不同的區域,每個區域都有個位域名,程序員可以代碼通過位域名訪問其中的數據。

位域的聲明

類型 位域名:位域長度;

位域結構體,我理解是一種特殊的結構體,其成員變量都是位域,聲明如下

struct 位域結構名 
{
  類型說明符 位域名:位域長度;
  ...
  類型說明符 位域名:位域長度;
};

基本原則

現有一個簡單的結構體

typedef struct Test1
{
    char a:1;
    int b:2;
}test1;

1. 位域變量的長度不能大於其類型的長度(sizeof(類型) * 8)

48264b03-3f3d-49dc-ade5-4785ed836cb8

變量char has_assoc的類型位char 1字節 8位,小於定義的10,所以編譯器警告

2.  不能用於位域字段的操作:取地址操作符&,取偏移量操作

位域是若干位空間,是沒有地址的

53a51dac-cfce-476d-842a-8dd83b231bb6

3. 位域可以是無名位域,無名位域只能用作填充或調整位置,不能使用。

typedef struct Test1
{
    char a:1;
    int b:2;
    int :1;
}test1;

4. 位域字段不能聲明為類的靜態成員

5. 位域結構體的大小必須是其最長基本類型大小的整數倍(sizeof(類型) * 8)

6.如果一個字節所剩空間不夠存放另一位域時,應從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如: 

struct bs     
{     
    unsigned a:4     
    unsigned :0 /*空域*/     
    unsigned b:4 /*從下一單元開始存放*/     
    unsigned c:4     
}

這個位域定義中,a占第一字節的4位,后4位填0表示不使用,b從第二字節開始,占用4位,c占用4位。

7.不夠一個類型的size時,將按其中最大的那個類型對齊。

struct foo4 {
    char    a : 2;
    char    b : 3;
    int c : 1;
};

foo4中雖然三個位域所占用空間之和為6 bit < 8 bit(1 byte),但是由於char和int的對齊系數是不同的,是不能捆綁在一起,那是不是a、b捆綁在一起按照char對齊,c單獨按照int對齊呢?我們 打印一下sizeof(struct foo4)發現結果為8,也就是說編譯器把a、b、c一起捆綁起來並以int做對齊了。

8.如果位域字段之間穿插着非位域字段,則不進行壓縮;

typedef struct Test1
{
    char a:1;
    int b:2;
}test1;
//運行結果:4
typedef struct Test1
{
    char a:1;
    int b:2;
    long c;
}test1;
//運行結果:16

總結:

1) 如果相鄰位域字段的類型相同,且其位寬之和小於類型的sizeof大小,則后面的字段將緊鄰前一個字段存儲,直到不能容納為止
2) 如果相鄰位域字段的類型相同,但其位寬之和大於類型的sizeof大小,則后面的字段將從新的存儲單元開始,其偏移量為其類型大小的整數倍;
3) 如果相鄰的位域字段的類型不同,則各編譯器的具體實現有差異,VC6采取不壓縮方式,GCC采取壓縮方式;
4) 如果位域字段之間穿插着非位域字段,則不進行壓縮;
5) 整個結構體的總大小為最寬基本類型成員大小的整數倍。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM