位域與結構體對齊

2021-05-22 07:57:58 字數 3214 閱讀 2879

一 位域

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

一、位域的定義和位域變數的說明位域定義與結構定義相仿,其形式為:

struct 位域結構名

;其中位域列表的形式為: 型別說明符 位網域名稱:位域長度

例如:struct bs

int a:8;

int b:2;

int c:6;

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

struct bs

int a:8;

int b:2;

int c:6;

}data;

說明data為bs變數,共佔兩個位元組。其中位域a佔8位,位域b佔2位,位域c佔6位。對於位域的定義尚有以下幾點說明:

struct bs

unsigned a:4

unsigned :0 /*空域*/

unsigned b:4 /*從下一成員變數開始存放*/

unsigned c:4

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

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

struct k

int a:1

int :2 /*該2位不能使用*/

int b:3

int c:2

從以上分析可以看出,位域在本質上就是一種結構型別, 不過其成員是按二進位分配的。

二、位域的使用

位域的使用和結構成員的使用相同,其一般形式為: 位域變數名·位網域名稱 位域允許用各種格式輸出。

main() bit,*pbit;

bit.a=1;

bit.b=7;

bit.c=15;

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

pbit=&bit;

pbit->a=0;

pbit->b&=3;

pbit->c|=1;

printf("%d,%d,%d/n",pbit->a,pbit->b,pbit->c);

上例程式中定義了位域結構bs,三個位域為a,b,c。說明了bs型別的變數bit和指向bs型別的指標變數pbit。這表示位域也是可以使用指標的。

程式的9、10、11三行分別給三個位域賦值。( 應注意賦值不能超過該位域的允許範圍)程式第12行以整型量格式輸出三個域的內容。第13行把位域變數bit的位址送給指標變數pbit。第14行用指標 方式給位域a重新賦值,賦為0。第15行使用了復合的位運算子"&=", 該行相當於: pbit->b=pbit->b&3位域b中原有值為7,與3作按位與運算的結果為3(111&011=011,十進位制值為 3)。同樣,程式第16行中使用了復合位運算"|=", 相當於: pbit->c=pbit->c|1其結果為15。程式第17行用指標方式輸出了這三個域的值。

為了節省空間,可以把幾個資料壓縮到少數的幾個型別空間上,比如需要表示二個3位二進位制的數,乙個2位二進位制的數,則可以用乙個8位的字元表示之。

使用位域的主要目的是壓縮儲存,其大致規則為:

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

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

3)  如果相鄰的位域字段的型別不同,則各編譯器的具體實現有差異,vc6採取不壓縮方式,dev-c++採取壓縮方式;

4)  如果位域字段之間穿插著非位域字段,則不進行壓縮;

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

int main(int argc, char* argv)

;struct s

;cout<

printf("press any key exit/n");

getch();

return 0;

}輸出:16  20

二 結構體對齊

#pragma pack(n)

資料邊界對齊方式:

以如下結構為例: struct

在windows預設結構大小: sizeof(struct) = 4+4+4+4=16;

與#pragma pack(4)一樣

若設為 #pragma pack(1), 則結構大小: sizeof(struct) = 1+2+4+1=8;

若設為 #pragma pack(2), 則結構大小: sizeof(struct) = 2+2+4+2=10;

在#pragma pack(1)時:空間是節省了,但訪問速度降低了;

例:#pragma pack(8)

struct s1;

struct s2;

問1.sizeof(s2) = ?

2.s2的c後面空了幾個位元組接著是d?

結果如下:

sizeof(s2)=24;s2的c後面空了3個位元組接著d.

成員對齊有乙個重要的條件,即每個成員分別對齊.即每個成員按自己的方式對齊.也就是說上面雖然指定了按8位元組對齊,但並不是所有的成員都是以8位元組對齊.其對齊的規則是,每個成員按其型別的對齊引數(通常是這個型別的大小)和指定對齊引數(這裡是8位元組)中較小的乙個對齊.並且結構的長度必須為所用過的所有對齊引數的整數倍,不夠就補空位元組.

s1中,成員a是2位元組預設按2位元組對齊,指定對齊引數為8,這兩個值中取2,a按2位元組對齊;成員b是4個位元組,預設是按4位元組對齊,這時就按4位元組對齊,所以sizeof(s1)應該為8;

s2 中,c按1位元組對齊,而d 是個結構,它是8個位元組,它按什麼對齊呢?對於結構來說,它的預設對齊方式就是它的所有成員使用的對齊引數中最大的乙個,s1的就是4.所以,成員d就是 按4位元組對齊.成員e是8個位元組,它是預設按8位元組對齊,和指定的一樣,所以它對到8位元組的邊界上,這時,已經使用了12個位元組了,所以又新增了4個位元組 的空,從第16個位元組開始放置成員e.這時,長度為24,已經可以被8(成員e按8位元組對齊)整除.這樣,一共使用了24個位元組.

結構體位元組對齊與位域

code advance struct c includestruct person int main 1.本身的成員變數型別 2.結構體存在位元組對齊 結構體內部最大的單成員型別的整數倍 如果下乙個成員無法在有限的空間存放則需要乙個額外的空間存放 3.如何優化位元組對齊 1.按照有限空間合理排布成...

C語言結構體位元組對齊與位域

一般的結構體 位域 include struct stu1 12位元組 可以看到,結構體大小並不是簡單的位元組相加。那麼,結構體為什麼不設定成位元組簡單相加而去為難我們呢?解 為了提高定址速度 我們可以試想結構體在呼叫成員的情況。比如呼叫成員c。它先找到我們定義的一大塊記憶體結構體s的首位址,flo...

結構體位元組對齊和位域對齊 VC gcc

分類 c c 2012 10 13 15 34 474人閱讀收藏 舉報 1 什麼是位元組對齊 乙個變數占用 n 個位元組,則該變數的起始位址必須能夠被 n 整除,即 存放起始地 址 n 0,對於結構體而言,這個 n 取其成員中的資料型別佔空間的值最大的那個。2 為什麼要位元組對齊 記憶體空間是按照位...