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数据类型提供一组访问函数。

相关文章
相关标签/搜索