關於結構體的位域

2021-10-07 16:30:15 字數 3527 閱讀 4097

說到位域,不得不說這是乙個很有意思的東西,我平時用得不太多,

因為這個東西在我的印象裡是對記憶體摳到極致迫不得已才會使用它的。

一般情況下我使用的硬體環境都還比較資源夠用,所以就不怎麼用,

但是既然提到了,也就寫一篇關於位域的文,

大概從以下幾個方面來說,

一、基本形式:

位域定義與結構定義相仿,其形式為:

struct 位域結構名

;

其中位域列表的形式為:

型別說明符 位網域名稱: 位域長度

例如:

typedef struct bs

bits;

​void test2(void);​

bit.a = 1;

bit.b = 4;

bit.c = 15;

​ printf("a:%d, b:%d, c:%d.\n", bit.a, bit.b, bit.c);

printf("sizeof(bit):%d.\n", sizeof(bit));}​

程式實際輸出:

a:1, b:4, c:15.

sizeof(bit):1.

//在這個位域定義中,其中位域a佔1位,位域b佔3位,位域c佔4位,共佔1個位元組空間。

二、儲存方式:

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

typedef struct bsbits;

2).乙個位域必須儲存在同乙個基本型別所佔的空間中,不能跨兩個基本型別所佔的空間。

typedef struct bsbits;

​void test(void);​

bit.a = 15;

bit.b = 15;

​ printf("a:%d, b:%d.\n", bit.a, bit.b);

printf("sizeof(bit):%d.\n", sizeof(bit));}​

程式實際輸出:

a:15, b:15.

sizeof(bit):2.

//在這個位域定義中,a佔第一位元組的4位,後4位填0表示不使用,

//b從第二位元組開始,占用4位。所以該位域變數佔2個位元組空間。

3).位域的長度不能大於乙個 位域基本型別所佔的空間大小 的bit位數

由於位域不允許跨兩個 位域基本型別所佔的空間,因此位域的長度不能大於乙個 位域基本型別所佔的空間大小 的bit位數,也就是說char 型別的位域不能超過8位,short 型別的位域不能超過16位,int 型別的位域不能超過32位。

4).位域字段在記憶體中的位置是按照從低位向高位的順序放置的,例如:

typedef struct bsbits;

typedef union uniunion;

void test(void)

​程式實際輸出:

uni.n = 32.

//位域中的位域字段按照從低位向高位順序方式的順序來看,

//那麼,a、b、c這三個位域字段在記憶體中的放置情況是:

//最高位是c:001,中間位是b:000,最低位是a:00。

//所以,這個位域結構中的8二進位制內容就是:00100000,總共8個位,其十進位制格式就是32。

5).位域字段不能是類的靜態成員.

如果上面2),3)說的不夠明白的話,可以總結為位域對齊,具體規則如下:

(1).如果相鄰位域字段的型別相同,且其位寬之和小於型別的sizeof大小,則後面的字段將緊鄰前乙個字段儲存,直到不能容納為止。

(2).如果相鄰位域字段的型別相同,但其位寬之和大於型別的sizeof大小,則後面的字段將從新的儲存單元開始,其偏移量為其型別大小的整數倍。

(3).如果相鄰的兩個位域字段的型別不同,則各個編譯器的具體實現有差異,vc6採取不壓縮方式,gcc和dev-c++都採用壓縮方式。

(4). 整個結構體的總大小為最寬基本型別成員大小的整數倍。

(5). 如果位域字段之間穿插著非位域字段,則不進行壓縮。(不針對所有的編譯器)

typedef struct bs

bits;

​void test(void);​

bit.b = 4;

bit.a = 3;

​ printf("a:%d, b:%d, &a:%d.\n", bit.a, bit.b, &bit.a);/* !!!這裡會報錯!!! */

//error: cannot take address of bit-field ...

printf("sizeof(bit):%d.\n", sizeof(bit));

}

原因是 bit-fields成員(通常)小於指標允許的粒度,這是chars的粒度(通過char的定義,順便說一下,它至少要求8位長)。因此,常規指標不會削減它。

此外,還不清楚指向位域成員的指標型別是什麼,因為要儲存/檢索這樣的成員,編譯器必須確切地知道它在位域中的位置(並且沒有"常規"指標型別可以攜帶此類資訊)。

最後,它幾乎不是乙個要求的功能(首先不會經常看到位域)。 bit-fields用於緊湊地儲存資訊或構建標誌的打包表示(例如寫入硬體埠),很少需要指向它們的單個欄位的指標。

由於所有這些原因,該標準表明位域成員不可定址。

2).由於大小端可能導致的問題

例如:

typedef struct bs

bits;

​void test(void)

; char result = 3;

memcpy(&bit, &result, 1);

printf("a:%d, b:%d, c:%d, d:%d.\n", bit.a, bit.b, bit.c, bit.d);

printf("sizeof(bit):%d.\n", sizeof(bit));

}

因為前面我們說過,位域字段在記憶體中的位置是按照從低位向高位的順序放置的,所以可以理解為:

**********====

高<=<=低

d  c  b  a

**********====

接下來我們看如何解析這個位元組:

在little-endian(小端)機器上,result位元組中各個位元的存放排列如下所示

**********====

高<=<=低

00000011

**********====

對應到四個位域,得

a=3,b=0,c=0,d=0

在big-endian(大端)機器上,result位元組中各個位元的存放排列如下所示

**********====

高<=<=低

11000000

**********====

對應到四個位域,得

a=0,b=0,c=1,d=1

由以上例子可以看出,在使用位域時,要注意cpu的大小端位元組序問題。

一定要先搞清楚大小端才能正確使用位域。

位結構體和位域

1.位域的定義 有些資訊在儲存時,並不需要占用乙個完整的位元組,而只需佔幾個或乙個二進位制位。例如在存放乙個開關量時,只有0和1 兩種狀態,用一位二進位即可。為了節省儲存空間,並使處理簡便,c語言又提供了一種資料結構,稱為 位域 或 位段 所謂 位域 是把乙個位元組中的二進位劃分為幾個不同的區域,並...

結構體和位域

c 陣列允許定義可儲存相同型別資料項的變數,結構是 c 程式設計中另一種使用者自定義的可用的資料型別,它允許您儲存不同型別的資料項。結構用於表示一條記錄,假設您想要跟蹤圖書館中書本的動態,您可能需要跟蹤每本書的下列屬性 為了定義結構,您必須使用struct語句。struct 語句定義了乙個包含多個成...

結構體及位域

結構體 結構體是一種集合,它裡面包含了多個變數或陣列,它們的型別可以相同,也可以不同,每個這樣的變數或陣列都稱為結構體的成員 member 結構體定義 struct st 這個結構體定義了整形變數a,浮點型變數 b,等等 注意 大括號後面的封號不能省略 2,結構體變數 類似於這些整形變數等等 定義結...