C/C++聯合(Union)淺談

聯合提供了一種方式,能夠規避C的類型系統,允許以多種類型來引用一個對象。聯合聲明的語法和結構體的語法一樣,只不過語義相差很大。它們不是用不同的域來引用不同的存儲器塊,而是引用同一塊存儲塊。

下面我們來舉幾個例子:

struct STest

{

       char   c;

       int    i[ 2 ];

       double var;

};

 

union UTest

{

       char   c;

       int    i[ 2 ];

       double var;

};

 

我們可以查看內存裏面的分佈:

類型         c     i    var    大小        

STest     0     4    12     20

UTest     0     0    0      8

上面的數據表示距離首地址的存儲器塊偏移。假如我們定義了UTest* pU; 我們分別察看p->c;  p->i[ 0 ];  p->var; 它們所引用的都是數據結構的起始位置。當然求sizeof的話。UTest的大小將是它的最大類型的數據成員的大小。

 

聯合的用處很多,這裏舉一個怎麼用它來節省空間:

假設我們有一個二叉樹的數據結構,每個葉子節點都有一個double的數據值,而每個內部節點都有指向孩子節點的指針,但是沒有數據(因爲是葉子節點)。如果我們像這樣聲明:

struct NODE

{

       struct NODE* pLeft;

       struct NODE* pRight;

       double       data;

};

我們可以知道這樣一個結構體需要16個字節,每個葉子節點都會浪費一半的字節。相反,如果我們用聯合來聲明一個節點:

union NODE

{

       struct

       {

              union NODE* pLeft;

              union NODE* pRight;

       }inter;

       double data;

};

這樣一來,每個節點就只需要8個字節。如果pNode是一個指向union NODE類型的指針,我們用pNode->data來引用葉子節點的數據。而pNode->inter.pLeft和pNode->inter.pRight來引用內部節點的孩子。

這樣可能出現一種情況,就是無法確定是哪種節點(內部節點或葉子節點)。我們可以引用一個標誌域。

struct NODE

{

       BOOL  isLeaf;

       union

       {

              struct

              {

                     union NODE* pLeft;

                     union NODE* pRight;

              }inter;

              double data;

       }info;

}

 

不過對於這樣小的節省而導致代碼的可讀性變得差了一些。在這裏聯合帶來的好處可以忽略。對於較多域的數據結構,這樣的節省會更加吸引人一些。

 

還有一個用法就是用來訪問不同數據類型的位。如:

UINT floatToBits( float fVar )

{

       union

       {

               float  fV;

               UINT uI;

       }temp;

       temp.fV = fVar;

       return temp.uI;

}

我們看看彙編代碼:

mov         eax,dword ptr [ fVar ]

mov         dword ptr [ temp ],eax

 

它跟下面的函數產生回彙編代碼是一樣的:

UINT floatToBits( UINT var )

{

       return var;

}

這就證明彙編代碼裏面缺乏信息,無論是什麼類型都相對於EBP偏移固定的值。過程只是簡單的拷貝,並沒有修改任何位。

 

再舉個例子吧:

double bitToDouble( UINT uParam1, UINT uParam2 )

{

       union

       {

               double d;

               UINT u[ 2 ];  

       }temp;

       temp.u[ 0 ] = uParam1;

       temp.u[ 1 ] = uParam2;

       return temp.d;

}

發佈了1 篇原創文章 · 獲贊 1 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章