天天看點

C語言 中結構體的位域(位段)

有些資訊在存儲時,并不需要占用一個完整的位元組, 而隻需占幾個或一個二進制位。
 
例如在存放一個開關量時,隻有0和1 兩種狀态, 用一位二進位即可。
 
為了節省存儲空間并使處理簡便,C語言又提供了一種資料結構,稱為“位域”或“位段”。所謂“位域”是把一個位元組中的二進位劃分為幾個不同的區域并說明每個區域的位數。每個域有一個域名,允許在程式中按域名進行操作。 這樣就可以把幾個不同的對象用一個位元組的二進制位域來表示。
 
 1.位域的聲明
 
位域變量的聲明與結構變量聲明的方式相同。 如:
 
Struct sample{
 
  int a:7;        //類型說明符 位域名:位域長度
 
  int b:2;
 
  int c:6;
 
}data;
 
其中,data為sample變量,共占兩個位元組。其中位域a占第一個位元組的7位,位域b占第二個位元組的低2位,位域c占第二個位元組的高6位。
 
2.位域的對齊
 
   如果結構體中含有位域(bit-field),那麼VC中準則是:
 
  1) 如果相鄰位域字段的類型相同且其位寬之和小于聲明資料類型的sizeof大小,則後面的字段将緊鄰前一個字段存儲,直到不能容納為止;
 
  2) 如果相鄰位域字段的類型相同但其位寬之和大于類型的sizeof大小(如:char 的位域長度不能超過8,int的位元組長度不能超過32),則後面的字段将從新的存儲單元開始,其偏移量為其類型大小的整數倍;
 
  3) 如果相鄰的位域字段的類型不同,則各編譯器的具體實作有差異,VC6采取不壓縮方式(不同位域字段存放在不同的位域類型位元組中),Dev-C++和GCC都采取壓縮方式;
 
  系統會先為結構體成員按照對齊方式配置設定空間和填塞(padding),然後對變量進行位域操作。
 
 
 
位域可以有無位域名,這時它隻用來作填充或調整位置。無名的位域是不能使用的。例如:
 
Struct sample{
 
  char a:7;    //類型說明符 位域名:位域長度
 
  char b:2;
 
  char :2;
 
        char c:2  //無位域名的位數 直接跳過且這2位不能使用
 
}data;
 
 
 
 
 
 
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <memory.h>
 
 
 
struct A{     //結構體位元組長度為8
 
    char a:8;          //占用第一個位元組的8位
 
    unsigned int b:5;     //占用第五個位元組的低5位
 
    unsigned int c:3;     //占用第五個位元組的高3位
 
};
 
 
 
int main()
 
{
 
    char testArry[10] = "0123456789";
 
    char testB[10] = {0};   
 
    struct A d;
 
 
 
     memcpy(&d, testArry, sizeof(d));
 
 
 
     printf("%d ", sizeof(d));
 
     printf("%d ", d.a);
 
     printf("%d ", d.b);
 
     printf("%d ", d.c);   
 
   
 
     system("pause");
 
     return 0;
 
}
 
 
 
編譯運作輸出結果:8  48  20  1
 
00110111 00110110 00110101 00110100   00110011 00110010 00110001 00110000