當前位置:首頁 » 編程語言 » c語言位域的存儲
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

c語言位域的存儲

發布時間: 2022-04-21 18:43:03

1. 解釋下位域,為什麼要用位域,位域的好處

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

使用位域的好處是:
1.有些信息在存儲時,並不需要佔用一個完整的位元組, 而只需占幾個或一個二進制位。例如在存放一個開關量時,只有0和1 兩種狀態, 用一位二進位即可。這樣節省存儲空間,而且處理簡便。 這樣就可以把幾個不同的對象用一個位元組的二進制位域來表示。
2.可以很方便的利用位域把一個變數給按位分解。比如只需要4個大小在0到3的隨即數,就可以只rand()一次,然後每個位域取2個二進制位即可,省時省空間。

2. C語言結構體位域問題

不是的,結構體變數只是整個結構體存儲的首地址,每個位域沒有具體規定大小,所以整個結構體也沒有規定大小,要看你定義的位域的類型。例如8個int型位域和8個double型位域存儲空間是不一樣的

3. C語言中「位域」與「域寬」有什麼區別。

有些信息在存儲時,並不需要佔用一個完整的位元組,而只需占幾個或一個二進制位。例如在存放一個開關量時,只有0和1
兩種狀態,用一位二進位即可。為了節省存儲空間,並使處理簡便,c語言又提供了一種數據結構,稱為「位域」或「位段」。所謂「位域」是把一個位元組中的二進位劃分為幾個不同的區域,並說明每個區域的位數。每個域有一個域名,允許在程序中按域名進行操作。這樣就可以把幾個不同的對象用一個位元組的二進制位域來表示。一、位域的定義和位域變數的說明位域定義與結構定義相仿,其形式為:
struct
位域結構名
{
位域列表
};
其中位域列表的形式為:
類型說明符
位域名:位域長度
例如:
struct
bs
{
int
a:8;
int
b:2;
int
c:6;
};

4. c語言 關於位域的使用

一、位域
有些信息在存儲時,並不需要佔用一個完整的位元組, 而只需占幾個或一個二進制位。例如在存放一個開關量時,只有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位。對於位域的定義尚有以下幾點說明:
1. 一個位域必須存儲在同一個位元組中,不能跨兩個位元組。如一個位元組所剩空間不夠存放另一位域時,應從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如:

struct bs
{
unsigned a:4
unsigned :0 /*空域*/
unsigned b:4 /*從下一單元開始存放*/
unsigned c:4
}
在這個位域定義中,a占第一位元組的4位,後4位填0表示不使用,b從第二位元組開始,佔用4位,c佔用4位。
2. 由於位域不允許跨兩個位元組,因此位域的長度不能大於一個位元組的長度,也就是說不能超過8位二進位。
3. 位域可以無位域名,這時它只用來作填充或調整位置。無名的位域是不能使用的。例如:

struct k
{
int a:1
int :2 /*該2位不能使用*/
int b:3
int c:2
};
從以上分析可以看出,位域在本質上就是一種結構類型, 不過其成員是按二進位分配的。
二、位域的使用
位域的使用和結構成員的使用相同,其一般形式為: 位域變數名·位域名 位域允許用各種格式輸出。

main(){
struct bs
{
unsigned a:1;
unsigned b:3;
unsigned c:4;
} 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行用指針方式輸出了這三個域的值。

5. C語言中關於位域的疑問

unsignedint:0;

寬度為 0 有特殊含義,表示如果前面一個 bit field 沒有占滿一個存儲單元,那麼這一個存儲單元剩下的位就不使用了。


不夠存儲就用下一位元組。

6. c語言 結構體位域問題

c存在第三個位元組

sizeof結構體,這個要看結構體內變數是如何定義的,結構體存放數據有個對齊原則,找到佔用最大位元組的變數,然後都向它對齊,比如bool和char類型佔用一個位元組,short占兩個位元組,int,float為4個位元組,double為八個位元組。

定義的順序不同,sizeof的結果不同。我給你舉個例子。

structA{
inta;
charb;
charc;
};


sizeof(A)應該為4+1+1,但是需要對齊,所以這個值就是8

圖2

這個是struct B的變數存儲

7. C語言中位域和結構體得區別是什麼

C語言結構體對齊也是老生常談的話題了。基本上是面試題的必考題。內容雖然很基礎,但一不小心就會弄錯。寫出一個struct,然後sizeof,你會不會經常對結果感到奇怪?sizeof的結果往往都比你聲明的變數總長度要大,這是怎麼回事呢?

開始學的時候,也被此類問題困擾很久。其實相關的文章很多,感覺說清楚的不多。結構體到底怎樣對齊?

有人給對齊原則做過總結,具體在哪裡看到現在已記不起來,這里引用一下前人的經驗(在沒有#pragma pack宏的情況下):

原則1、數據成員對齊規則:結構(struct或聯合union)的數據成員,第一個數據成員放在offset為0的地方,以後每個數據成員存儲的起始位置要從該成員大小的整數倍開始(比如int在32位機為4位元組,則要從4的整數倍地址開始存儲)。

原則2、結構體作為成員:如果一個結構里有某些結構體成員,則結構體成員要從其內部最大元素大小的整數倍地址開始存儲。(struct a里存有struct b,b里有char,int,double等元素,那b應該從8的整數倍開始存儲。)

原則3、收尾工作:結構體的總大小,也就是sizeof的結果,必須是其內部最大成員的整數倍,不足的要補齊。

這三個原則具體怎樣理解呢?我們看下面幾個例子,通過實例來加深理解。

例1:struct {
short a1;
short a2;
short a3;
}A;

struct{
long a1;
short a2;
}B;

sizeof(A) = 6; 這個很好理解,三個short都為2。

sizeof(B) = 8; 這個比是不是比預想的大2個位元組?long為4,short為2,整個為8,因為原則3。

例2:struct A{
int a;
char b;
short c;
};

struct B{
char b;
int a;
short c;
};

sizeof(A) = 8; int為4,char為1,short為2,這里用到了原則1和原則3。

sizeof(B) = 12; 是否超出預想范圍?char為1,int為4,short為2,怎麼會是12?還是原則1和原則3。

深究一下,為什麼是這樣,我們可以看看內存里的布局情況。

a b c
A的內存布局:1111, 1*, 11

b a c
B的內存布局:1***, 1111, 11**

其中星號*表示填充的位元組。A中,b後面為何要補充一個位元組?因為c為short,其起始位置要為2的倍數,就是原則1。c的後面沒有補充,因為b和c正好佔用4個位元組,整個A佔用空間為4的倍數,也就是最大成員int類型的倍數,所以不用補充。

B中,b是char為1,b後面補充了3個位元組,因為a是int為4,根據原則1,起始位置要為4的倍數,所以b後面要補充3個位元組。c後面補充兩個位元組,根據原則3,整個B佔用空間要為4的倍數,c後面不補充,整個B的空間為10,不符,所以要補充2個位元組。

再看一個結構中含有結構成員的例子:

例3:struct A{
int a;
double b;
float c;
};

struct B{
char e[2];
int f;
double g;
short h;
struct A i;
};

sizeof(A) = 24; 這個比較好理解,int為4,double為8,float為4,總長為8的倍數,補齊,所以整個A為24。

sizeof(B) = 48; 看看B的內存布局。

e f g h i
B的內存布局:11* *, 1111, 11111111, 11 * * * * * *, 1111* * * *, 11111111, 1111 * * * *

i其實就是A的內存布局。i的起始位置要為24的倍數,所以h後面要補齊。把B的內存布局弄清楚,有關結構體的對齊方式基本就算掌握了。

以上講的都是沒有#pragma pack宏的情況,如果有#pragma pack宏,對齊方式按照宏的定義來。比如上面的結構體前加#pragma pack(1),內存的布局就會完全改變。sizeof(A) = 16; sizeof(B) = 32;

有了#pragma pack(1),內存不會再遵循原則1和原則3了,按1位元組對齊。沒錯,這不是理想中的沒有內存對齊的世界嗎。

a b c
A的內存布局:1111, 11111111, 1111

e f g h i
B的內存布局:11, 1111, 11111111, 11 , 1111, 11111111, 1111

那#pragma pack(2)的結果又是多少呢?#pragma pack(4)呢?留給大家自己思考吧,相信沒有問題。

還有一種常見的情況,結構體中含位域欄位。位域成員不能單獨被取sizeof值。C99規定int、unsigned int和bool可以作為位域類型,但編譯器幾乎都對此作了擴展,允許其它類型類型的存在。

使用位域的主要目的是壓縮存儲,其大致規則為:
1) 如果相鄰位域欄位的類型相同,且其位寬之和小於類型的sizeof大小,則後面的欄位將緊鄰前一個欄位存儲,直到不能容納為止;
2) 如果相鄰位域欄位的類型相同,但其位寬之和大於類型的sizeof大小,則後面的欄位將從新的存儲單元開始,其偏移量為其類型大小的整數倍;
3) 如果相鄰的位域欄位的類型不同,則各編譯器的具體實現有差異,VC6採取不壓縮方式,Dev-C++採取壓縮方式;
4) 如果位域欄位之間穿插著非位域欄位,則不進行壓縮;
5) 整個結構體的總大小為最寬基本類型成員大小的整數倍。

還是讓我們來看看例子。

例4:struct A{
char f1 : 3;
char f2 : 4;
char f3 : 5;
};

a b c
A的內存布局:111, 1111 *, 11111 * * *

位域類型為char,第1個位元組僅能容納下f1和f2,所以f2被壓縮到第1個位元組中,而f3隻能從下一個位元組開始。因此sizeof(A)的結果為2。

例5:struct B{
char f1 : 3;
short f2 : 4;
char f3 : 5;
};

由於相鄰位域類型不同,在VC6中其sizeof為6,在Dev-C++中為2。

例6:struct C{
char f1 : 3;
char f2;
char f3 : 5;
};

非位域欄位穿插在其中,不會產生壓縮,在VC6和Dev-C++中得到的大小均為3。

考慮一個問題,為什麼要設計內存對齊的處理方式呢?如果體系結構是不對齊的,成員將會一個挨一個存儲,顯然對齊更浪費了空間。那麼為什麼要使用對齊呢?體系結構的對齊和不對齊,是在時間和空間上的一個權衡。對齊節省了時間。假設一個體系結構的字長為w,那麼它同時就假設了在這種體系結構上對寬度為w的數據的處理最頻繁也是最重要的。它的設計也是從優先提高對w位數據操作的效率來考慮的。有興趣的可以google一下,人家就可以跟你解釋的,一大堆的道理。

最後順便提一點,在設計結構體的時候,一般會尊照一個習慣,就是把佔用空間小的類型排在前面,佔用空間大的類型排在後面,這樣可以相對節約一些對齊空間。

本篇文章來源於:開發學院 http://e.codepub.com 原文鏈接:http://e.codepub.com/2010/0318/21111.php

8. 關於C語言 含位域結構體的內存大小的疑問

因為這里又涉及到了結構體內存對齊的知識,對於VC和GCC下面的對齊模數都是4

存放完short類型的數據後,後面還有2個位元組沒有使用,內存分布大約是這樣的

[ncack_sn:10][e1:1][e2:1][填充:20]
[start:15][end:15][填充:2]

總共佔8個位元組

typedefstructnack_sn{

unsignedshortncack_sn:10;

unsignedshorte1:1;

unsignedshorte2:1;

unsignedintstart:15;

unsignedintend:15;

}nack_sn_t;

9. 關於c語言的「位域」。

聲明是我拷貝過來的,不過說的很好。
位域
有些信息在存儲時,並不需要佔用一個完整的位元組, 而只需占幾個或一個二進制位。例如在存放一個開關量時,只有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位。對於位域的定義尚有以下幾點說明:
1. 一個位域必須存儲在同一個位元組中,不能跨兩個位元組。如一個位元組所剩空間不夠存放另一位域時,應從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如:

struct bs
{
unsigned a:4
unsigned :0 /*空域*/
unsigned b:4 /*從下一單元開始存放*/
unsigned c:4
}
在這個位域定義中,a占第一位元組的4位,後4位填0表示不使用,b從第二位元組開始,佔用4位,c佔用4位。
2. 由於位域不允許跨兩個位元組,因此位域的長度不能大於一個位元組的長度,也就是說不能超過8位二進位。
3. 位域可以無位域名,這時它只用來作填充或調整位置。無名的位域是不能使用的。例如:

struct k
{
int a:1
int :2 /*該2位不能使用*/
int b:3
int c:2
};
從以上分析可以看出,位域在本質上就是一種結構類型, 不過其成員是按二進位分配的。
二、位域的使用
位域的使用和結構成員的使用相同,其一般形式為: 位域變數名·位域名 位域允許用各種格式輸出。

main(){
struct bs
{
unsigned a:1;
unsigned b:3;
unsigned c:4;
} 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位的字元表示之。
struct
{
char a : 3;
char b : 3;
char c : 2;
} ;
這個結構體所佔空間為一個位元組,8位。節省了空間。

10. 求C語言位域物理存儲形式

ww的結構應該是這樣的
[
addr
]
[dd|cc|bb|xx]
通過以下代碼可以很清楚看出結構
#include
<stdio.h>
typedef
struct
{
char
addr
:
8;
char
xx
:
4;
char
bb:
1;
char
cc:
2;
char
dd:
1;
}ww;
int
main(void)
{
ww
w;
int
i;
char
*p
=
(char*)&w;
memset(&w,
0,
sizeof(w));
w.dd
=
1;
printf("sizeof(w)
=
%d\n",
sizeof(w));
for(i
=
0;
i
<
sizeof(w);
++i)
printf("%2x\n",
*(p+i));
getchar();
}