位段(轉)


其存儲位置一般從右至左進行存儲即:data: c(6bits) | b(2bits) | a(8bits).   依編譯器而定,TMS320的DSP的CCS按右至左的順序。
對於位域的定義尚有以下幾點說明
0)位段成員的類型必須指定為unsigned int類型;
1)       一個位域必須存儲在同一個字節中,不能跨兩個字節。如一個字節所剩空間不夠存放另一位域時,應從下一單元起存放該位域。也可以有意使某位域從下一單元開始;
2)       由於位域不允許跨兩個字節,因此位域的長度不能大於一個字節的長度,也就是說不能超過8位二進位。
3)       位域可以無位域名,這時它只用來作填充或調整位置。無名的位域是不能使用的
 
  • 在某些機器上, 位段總是作為 unsigned 處理, 而不管它們是否被說明成 unsigned 的。
  • 大多數C 編譯器都不支持超過一個字長的位段。
  • 位段不可標明維數; 即, 不能說明位段數組, 例如 flag:l[2]。
  • 最后, 不可以取位段地址。原因是, 在這種情況不, 顯然沒有稱作為 "位段指針" 類型的變量
 

file1:

http://hi.baidu.com/jevidyang/blog/item/5f2dc503d3c481763812bb6c.html

位域(位段)

有些信息在存儲時,並不需要占用一個完整的字節,而只需占幾個或一個二進制位。例如在存放一個開關量時,只有01兩種狀態,用一位二進位即可。為了節省存儲空間,並使處理簡便,C語言又提供了一種數據結構,稱為位域位段

所謂“位域”是把一個字節中的二進位划分為幾個不同的區域,並說明每個區域的位數。每個域有一個域名,允許在程序中按域名進行操作。這樣就可以把幾個不同的對象用一個字節的二進制位域來表示。

1.     位域的定義和位域變量的說明

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

    struct 位域結構名

       { 位域列表 };

其中位域列表的形式為:

    類型說明符位域名:位域長度  

例如:

    struct bs

     {

       unsigned a:8;

       unsigned b:2;

       unsigned c:6;

     };

位域變量的說明與結構變量說明的方式相同。可采用先定義后說明,同時定義說明或者直接說明這三種方式。

例如:

    struct bs

     {

       unsigned a:8;

       unsigned b:2;

          unsignedc:6;

     }data;

 

說明databs變量,共占兩個字節。其中位域a8位,位域b2位,位域c6位。

其存儲位置一般從右至左進行存儲即:data: c(6bits) | b(2bits) | a(8bits).  依編譯器而定,TMS320的DSP的CCS按右至左的順序。

 

對於位域的定義尚有以下幾點說明

0)位段成員的類型必須指定為unsigned int類型;

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

     {

      unsigned a:1

      unsigned  :2          /*2位不能使用*/

      unsigned b:3

      unsigned c:2

     };

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

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。這表示位域也是可以使用指針的。程序的91011三行分別給三個位域賦值(應注意賦值不能超過該位域的允許范圍)。程序第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行用指針方式輸出了這三個域的值。

 

file2:

http://blog.sina.com.cn/u/489e70e1010005tn

1.什么是位段

在大多數的計算機系統中, 一個字節是由八個更小的, 稱作為位的單位組成的。位是比字節更小的單位。位只有兩個值,  1 或  0 。因此, 存儲在計算機存儲器中的一個字節可以看成由八個二進制數字形成的串。

例如, 一個存放值 36 的字節是八個二進制數字的串: 可以表示成 00100100。 存入值24 的字節可以表示成 00010100。

有時, 我們希望不僅對字節進行操作, 也要能對位進行操作。例如, 用布爾真或假條件表示的標志, 在計算機中可用位來表示。

但是, 說明一個用作標志的普通變量至少要用一個字節---8 位, 而在某些計算機系統中則可能是 16 位。如果我們想在一個很大的表中存儲很多標志, 那么 "被浪費" 的內存空間是很可觀的。在 C 語言中, 一種方法是用叫做位段的構造類型來定義一個壓縮信息的結構。
位段什么是位段呢? 位段是 C 語言特有的數據結構, 它允許我們定義一個由位組成的段, 並可為它賦以一個名字。

2.位段的用法

我們已經了解什么是位段了, 現在我們繼續討論位段的使用方法。

先看一個例子: 我們需要用到五個變量。 假定, 其中三個用作標志, 稱為 f1, f2 和 f3。
第四個稱為 type, 取值范圍為 1 至 12。 最后一個變量稱為 index, 值的范圍為 0 至 500。

通常, 我們用下面的語句來說明這些變量:
char f1,f2,f3;
unsigned int type;
unsigned int index;

但是, 實際上標志 f1, f2, f3 分別只需要 1 位。變量 type 只需要 4 位, 而變量 index 只需要 9 位。 總共是 16位 ---- 2 個字節。我們用兩個字節就夠了。

我們可這樣來做:
struct packed_struct
{
    unsigned int f1 :1;
    unsigned int f2 :1;
    unsigned int f3 :1;
    unsigned int type :4;
    unsigned int index :9;
};
位段該例中, 我們定義了一個結構 packed_struct。該結構定義了五個成員。第一個成員叫做 f1, 是 unsigned int 類型的。緊跟在該成員名之后的 :1 規定了它以 1 位存放。類似地, 標志 f2 和 f3 被定義為長度只有 1 位的。定義成員 type 占有 4 位。定義成員 index 占有 9 位。C 編譯器自動地把上面的位段定義壓縮在一起。位段的划分如圖所示。packed_struct 總共使用了 16 位。

這種方法的好處是, 定義成 packed_struct 類型的變量的位段, 可以如引用一般的結構成員一樣方便地引用。同時, 使用了更少的內存單元數。

我們已經定義了一個稱作為 packed_struct 的包含着位段的結構。現在, 我們象下面那樣定義一個稱作為 packet_data 的變量: struct packed_struct packed_data; 於是, 我們就可以用簡單的語句, 把 packed_data 的 type 位段設置為 7:
packed_data.type = 7; 類似地, 我們可以用下面的語句把這個位段的值設為 n:
packed_data.type = n; 我們不必擔心 n 的值太長, 以致不能放入 type 位段中, C 編譯器會自動地僅取出 n 的低四位, 把它賦值給 packed_data.type。取出位段的值也自動地處理的, 因此語句 n = packed_data.type; 將從 packed_data 中取出 type 位段, 並把它的值賦給 n。

在一般的表達式中可以使用位段, 此時, 位段自動地轉換成整數。因此, 表達式
i = packed_data.index/5+1; 是完全有效的。

在包含位段的結構中, 也可以包括 "通常的" 數據類型。因此, 如果我們想定義一個結構, 它包含一個 int, 一個 char, 和二個 1 位的標志, 那么, 下面的定義是有效的:
struct table_entry
{
    int     count ;
    char     c;
    unsigned int f1 :1;
    unsigned int f2 :1;
};


當位段出現在結構定義中時, 它們就被壓縮成字。如果某個位段無法放入一個字中, 那么該字的剩余部分跳過不用, 該位段被放入下一個字中。

使用位段時, 必須注意下列事項:
  • 在某些機器上, 位段總是作為 unsigned 處理, 而不管它們是否被說明成 unsigned 的。
  • 大多數C 編譯器都不支持超過一個字長的位段。
  • 位段不可標明維數; 即, 不能說明位段數組, 例如 flag:l[2]。
  • 最后, 不可以取位段地址。原因是, 在這種情況不, 顯然沒有稱作為 "位段指針" 類型的變量。
這里, 我們再深入討論一下位段。如果使用下面的結構定義:
struct bits
{
    unsigned int f1:1;
    int     word;
    unsigned int f3:1;
};
位段
那么, 位段是怎樣壓縮的呢? 由於成員 word 出現於其間, 故 f1, f3 不會壓縮在同一個字內。C 編譯器不會重新安排位段定義來試圖優化存儲空間。
可以指定無名位段, 使得一個字中的某些位被 "跳過"。因此, 定義:
struct x_entry
{
    unsigned int type :4;
    unsigned int :3;
    unsigned int count :9;
};
位段
將定義一個結構 x_entry, 它包含兩個位段變量 type 和 count, 而無名位段規定了 type 和 count 間隔三位。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM