c++ union學習

看到公司前輩的代碼中用到了union,不論是大學仍是工做用到union機會比較少,仍是挺新奇的.因此特地找些資料學習學習html

前輩的代碼:ios

 1 #include<iostream>
 2 using namespace std;
 3 
 4 typedef  unsigned int     UINT32; 
 5 typedef  unsigned char    UINT8; 
 6 typedef  unsigned short   UINT16;
 7 
 8 union date
 9 {
10     UINT32 value;
11     struct
12     {
13         UINT8    day;
14         UINT8    month;
15         UINT16    year;
16     };
17 }__attribute__((packed));
18 int main(int argc, char** argv)
19 {
20     date myDate;
21     myDate.day = 02;
22     myDate.month = 10;
23     myDate.year = 2014;
24     cout<<hex<<myDate.value<<dec<<endl;    
25     return 0;
26 }
27 //輸出結果   0x7de0a02--->02對應day  0a對應month   7de對應2014 (計算過程  16*16*7+16*13+14)

下面是找的學習帖子:   http://blog.sina.com.cn/s/blog_660234cf0100wsgs.html網絡

union主要是共享內存,分配內存以其最大的結構或對象爲大小,即sizeof最大的。在C/C++程序的編寫中,當多個基本數據類型或複合數據結構要佔用同一片內存時,咱們要使用聯合體當多種類型,多個對象,多個事物只取其一時(咱們姑且通俗地稱其爲「n 選1」),咱們也可使用聯合體來發揮其長處數據結構

 1 union myun
 2 {
 3 struct { int x; int y; int z; }u;
 4 int k;
 5 }a;
 6 int main()
 7 {
 8 a.u.x =4;
 9 a.u.y =5;
10 a.u.z =6;
11 a.k = 0;
12 printf("%d %d %d\n",a.u.x,a.u.y,a.u.z);  //0 5 6 13 return 0;
14 }
myun這個結構就包含u這個結構體,而大小也等於u這個結構體 的大小,在內存中的排列爲聲明的順序x,y,z從低到高,而後賦值的時候,在內存中,就是x的位置放置4,y的位置放置5,z的位置放置6,如今對k賦 值,對k的賦值由於是union,要共享內存,因此從union的首地址開始放置,首地址開始的位置實際上是x的位置,這樣原來內存中x的位置就被k所賦的 值代替了,就變爲0了
再看兩個試題:

試題一:編寫一段程序判斷系統中的CPU 是Little endian 仍是Big endian 模式?
分析:
Little endian 和Big endian 是CPU 存放數據的兩種不一樣順序。對於整型、長整型等數據類型,Big endian 認爲第一個字節是最高位字節(按照從低地址到高地址的順序存放數據的高位字節到低位字節);而Little endian 則相反,它認爲第一個字節是最低位字節(按照從低地址到高地址的順序存放數據的低位字節到高位字節)。函數

--------------------------------------------------------------------------------------
例如
學習

------------------------------------------------------------------------------------------------
通常來講,x86 系列CPU 都是little-endian 的字節序,PowerPC 一般是Big endian,還有的CPU 能經過跳線來設置CPU 工做於Little endian 仍是Big endian 模式。spa

解答:
顯然,解答這個問題的方法只能是將一個字節(CHAR/BYTE 類型)的數據和一個整型數據存放於一樣的內存開始地址,經過讀取整型數據,分析CHAR/BYTE 數據在整型數據的高位仍是低位來判斷CPU 工做於Littleendian 仍是Big endian 模式。得出以下的答案:操作系統

 
 

int main(int argc, char** argv)
{
int i = 0x12345678;
char* p = reinterpret_cast<char*>(&i);
cout<<hex<<static_cast<int>(*p)<<endl;
return 0;
}  //若是輸出是78就是小段  若是輸出是34就是大端.net

除了上述方法(經過指針類型強制轉換並對整型數據首字節賦值,判斷該賦值賦給了高位仍是低位)外,還有沒
有更好的辦法呢?咱們知道,union 的成員自己就被存放在相同的內存空間(共享內存,正是union 發揮做用、作貢獻的去處),所以,咱們能夠將一個CHAR/BYTE 數據和一個整型數據同時做爲一個union 的成員,得出
以下答案:3d

 1 int checkCPU()
 2 {
 3     {
 4         union w
 5         {
 6             int a;
 7             char b;
 8         } c;
 9         c.a = 1;
10         return (c.b == 1);    //小端的話 c.b == 1  不然c.b == 0
11     }
12 }        

實現一樣的功能,咱們來看看Linux 操做系統中相關的源代碼是怎麼作的:

1 static union
2  { 
3         char c[4]; 
4         unsigned long mylong; 
5 } endian_test = {{ 'l', '?', '?', 'b' } };
6 
7 #define ENDIANNESS ((char)endian_test.mylong)

Linux 的內核做者們僅僅用一個union 變量和一個簡單的宏定義就實現了一大段代碼一樣的功能!由以上一段代碼咱們能夠深入領會到Linux 源代碼的精妙之處!(若是ENDIANNESS=’1’表示系統爲little endian,爲’b’表示big endian )

-------------------------

試題二:假設網絡節點A 和網絡節點B 中的通訊協議涉及四類報文,報文格式爲「報文類型字段+報文內容的結構體」,四個報文內容的結構體類型分別爲STRUCTTYPE1~ STRUCTTYPE4,請編寫程序以最簡單的方式組織一個統一的報文數據結構。
分析:
報文的格式爲「報文類型+報文內容的結構體」,在真實的通訊中,每次只能發四類報文中的一種,咱們能夠將四類報文的結構體組織爲一個union(共享一段內存,但每次有效的只是一種),而後和報文類型字段統一組織成一個報文數據結構。
解答:
根據上述分析,咱們很天然地得出以下答案:

1 typedef unsigned char BYTE;
2 //報文內容聯合體
3 typedef union tagPacketContent
4 {
5     STRUCTTYPE1 pkt1;
6     STRUCTTYPE2 pkt2;
7     STRUCTTYPE3 pkt1;
8     STRUCTTYPE4 pkt2;
9 }PacketContent;

//統一的報文數據結構

1 typedef struct tagPacket
2 {
3     BYTE pktType;
4     PacketContent pktContent;
5 }Packet;

 --------------------------------------------------------------------

繼續學習

http://baike.so.com/doc/200726-212218.html

http://blog.csdn.net/lincyang/article/details/6176642

 首先是union的大小問題

    能夠看出來union也使用相似struct的內存大小分配方式.

對應union Stu2來講 最大是10 可是最小單位是4 因此會擴展成4*3=12.

union結構體對成員變量的要求:

union的成員不能夠爲靜態、引用[理由是聯合裏面的東西是共享內存的,而靜態和引用不可能共享內存]若是是自訂型態的話,該自訂型態成員不能夠有建構函式、解構函式或是複製指定運算子

如下就是錯誤的形式[理由是帶有構造函數、析夠函數、複製拷貝操做符等的類他們共享內存,編譯器沒法保證這些對象不被破壞,也沒法保證離開時調用析夠函數。]

固然.若是你不主動提供構造函數,而使用類或者結構體默認的構造函數是能夠的.

  

在class中定義union對象

錯誤代碼 正確代碼 緣由分析
 

錯誤代碼之因此錯誤是由於在構造函數的

初始化列表的時候 根本就尚未data對象

有何談data的成員變量ch呢

如何有效的防止union的訪問錯誤

使用聯合能夠節省內存空間,可是也有必定的風險:經過一個不適當的數據成員獲取當前對象的值!例如上面的ch、i交錯訪問。爲了防止這樣的錯誤,咱們必須定義一個額外的對象,來跟蹤當前被存儲在聯合中的值得類型,咱們稱這個額外的對象爲:union的判別式(例如上例中的enum type)。 一個比較好的經驗是,在處理做爲類成員的union對象時,爲全部union數據類型提供一組訪問函數。

相關文章
相關標籤/搜索