位域用法

流水江湖發表於2024-04-21

資訊處理中,有些資訊在儲存時,並不需要佔用一個完整的位元組,而只需佔一個或幾個位元位。例如在存放一個開關量時,只有0和1 兩種狀態, 用一位二進位制位即可。為了節省儲存空間,並使處理簡便,C語言又提供了一種資料結構,稱為“位域”或“位段”。
所謂“位域”是把一個位元組中的位元位劃分為幾個不同的區域, 並說明每個區域的位數。每個域有一個域名,允許在程式中按域名進行操作。 這樣就可以把幾個不同的物件用一個位元組的二進位制位域來表示。位域在本質上就是一種結構型別, 不過其成員是按二進位制位分配的。

1.位域的定義
位域是透過結構體來定義的,相比較普通的結構體,位域的成員需要明確標註其所佔位元位的長度。
位域定義的基本語法如下:

struct 位域結構體名 
{
	位域列表 
};

其中位域列表 “型別說明符  位域名 : 位域長度;”

2.位域變數的定義
位域變數的說明與結構變數說明的方式相同。 可採用先定義後說明、同時定義說明、直接說明這三種方式。
例如:

struct BitField
{
	char a:8;
	char b:2;
	char c:5;
}weiyu; 

weiyu為BitField變數,共佔兩個位元組。

3.位域的注意事項
1)一個位域必須儲存在同一個儲存單元中,不能跨兩個儲存單元。
2)一個儲存單元所剩空間不夠存放另一位域時,應從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如:

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

在這個位域定義中,a佔第一位元組的4位,後4位填0表示不使用,b從第二位元組開始,佔用4位,c佔用4位。

3) 位域可以無位域名,這時它只用來作填充或調整位置。無名的位域是不能使用的。例如:

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

4)位域列表中,儘可能不要出現不同型別的域,否則,不同的編譯器下得到的位域的長度將不一致。

4.位域的使用
位域的使用和結構成員的使用相同,其一般形式為: 位域變數名·位域名

5.位域在記憶體中儲存模式
不同的晶片儲存次序是不同的,對於Intel晶片,是按照從低位開始儲存的,而對於Motolola晶片則正好相反。因此在使用不同晶片之間進行資料傳輸使用位域儲存的資料的時候,必須知道是否是相同的晶片之間的資料傳輸,因為在資訊的接收端要確保按照正確的次序讀取相應的位域,否則將會發生不可預知的錯誤!!!

三、位域示例

Demo1:對某位域分別賦值,之後對位域進行不同的賦值或者位運算,並分別向螢幕輸出位域。

#include"stdio.h"
struct bf
{
	unsigned char a:1;
	unsigned char b:3;
	unsigned char c:3;
};
int main()
{
	bf bit, *pbit;
	bit.a = 1;
	bit.b = 7;
	bit.c = 2;
	printf(" %d,%d,%d\n",bit.a,bit.b,bit.c);
	pbit = &bit;
	pbit->a = 0;
	pbit->b &= 0x5;
	pbit->c |= 0x5;
	printf(" %d,%d,%d\n",pbit->a,pbit->b,pbit->c);
	printf( " length of bitfield : %d", sizeof( bf ) );
return 0;
}

Demo2:對位域整體進行賦值,之後分別輸出每個位域

#include"stdio.h"
struct BF
{
	unsigned char a:5;
	unsigned char b:2;
	unsigned char c:4;
};
int main()
{
	BF *val;
	unsigned short aa = 1000;//1111101000
	val = ( struct BF * )&aa;
	printf(" BF.a = %d\n", val->a);
	printf(" BF.b = %d\n", val->b);
	printf(" BF.c = %d\n", val->c);
	return 0;
}

記憶體狀態

位域用法

可以看出,位域其實就是一種結構型別, 只不過成員佔用空間大小是按Bit分配的。

相關文章