參考鏈接 https://blog.csdn.net/yanbober/article/details/8697967 https://blog.csdn.net/Tommy_wxie/article/details/43529407
我們都知道信息的存取在高級語言中最小是Byte,以字節為單位的,雖然C語言提供了位操作符&,|,~,<< >>可以對一個整數進行位操作,但是並沒有對內存進行優化。現實生活中我們常常需要一個標志值真或者假,即可以用二進制0或者1表示,這種情況很常見,如開關,過程控制、參數檢測或數據通信領域時,控制信息往往只占一個字節中的一個或幾個二進制位,基於此,C語言支持位域定義可以幫我們解決這個問題。
C語言允許在結構體(聯合體)中以位為單位來指定其成員變量所占的內存單元,這種以位為單位的成員稱為“位段”或稱“位域”( bit field) 。利用位段能夠用較少的位數存儲數據。位段(bit-field)是以位為單位來定義結構體(或聯合體)中的成員變量所占的空間。含有位段的結構體(聯合體)稱為位段結構。采用位段結構既能夠節省空間,又方便於操作。
定義:
位域定義與結構定義相仿,其形式為:
struct 位域結構名
{ 位域列表 };
其中位域列表的形式為: 類型說明符 位域名:位域長度
type [var]:digits
其中,type只能為int,unsigned int,signed int三種類型(int型能不能表示負數視編譯器而定,比如VC中int就默認是signed int,能夠表示負數)。位段名稱var是可選參數,即可以省略。digits表示該位段所占的二進制位數。
使用位段需注意一下幾點:
1)位段的類型只能是int,unsigned int,signed int三種類型,不能是char型或者浮點型;
2)位段占的二進制位數不能超過該基本類型所能表示的最大位數,比如在VC中int是占4個字節,那么最多只能是32位;
3)無名位段不能被訪問,但是會占據空間;
4)不能對位段進行取地址操作;
5)若位段占的二進制位數為0,則這個位段必須是無名位段,下一個位段從下一個位段存儲單元(這里的位段存儲單元經測試在VC環境下 是4個字節)開始存放;
6)若位段出現在表達式中,則會自動進行整型升級,自動轉換為int型或者unsigned int。
7)對位段賦值時,最好不要超過位段所能表示的最大范圍,否則可能會造成意想不到的結果。
8)位段不能出現數組的形式。
二位段結構在內存中的存儲方式
對於位段結構,編譯器會自動進行存儲空間的優化,主要有這幾條原則:
1)如果一個位段存儲單元能夠存儲得下位段結構中的所有成員,那么位段結構中的所有成員只能放在一個位段存儲單元中,不能放在兩個位段存儲單元中;如果一個位段存儲單元不能容納下位段結構中的所有成員,那么從剩余的位段從下一個位段存儲單元開始存放。(在VC中位段存儲單元的大小是4字節).
2)如果一個位段結構中只有一個占有0位的無名位段,則只占1或0字節的空間(C語言中是占0字節,而C++中占1字節);否則其他任何情況下,一個位段結構所占的空間至少是一個位段存儲單元的大小;
下面以具體例子來講解:
#include <stdio.h>
#include <iostream>
using namespace std;
typedef struct{
unsigned int a:1; //存在一個非0位的位段,則至少占4Byte,注意是至少
}s;
typedef struct {
unsigned _int64 a:33; //這個占8字節
}ss;
typedef struct {
unsigned int :0; //存在一個0位的位段,C編譯器占0字節,C++編譯器占1字節
}s1;
typedef struct {
unsigned int a:1;
unsigned :0; //下一個位段放在一個新的位段存儲單元 ,所以占4+4=8Byte
unsigned int b:2;
}s2;
typedef struct {
unsigned int a:4;
unsigned int b:32; //由於4+32》32,所以b放在一個新的位段中 4+4=8字節
}s3;
typedef struct {
unsigned int a:1;
char b; //這個加起來總共不超過4字節,占一個位段
int c:1;
int d:2;
unsigned int e:2;
}S4;
extern int testBit()
{
S4 s4;
s4.a=1;
s4.b='a';
s4.c=1;
s4.d=2;
s4.e=2;
cout<<s4.a<<"\t"<<s4.b<<"\t"<<s4.c<<"\t"<<s4.d<<"\t"<<s4.e<<endl;
printf("sizeof(s)=%d\nsizeof(s1)=%d\nsizeof(s2)=%d\nsizeof(s3)=%d\nsizeof(s4)=%d\n",
sizeof(s),sizeof(s1),sizeof(s2),sizeof(s3),sizeof(s4));
cout<<sizeof(ss)<<endl;
return 0;
}
以下鏈接是一個不錯的練習體
http://its.nbtvu.net.cn/xhyu/cai_c/c_web/c/c8/c83.htm
下一篇介紹位段在0_1背包中的蠻力法應用案例
