union关键字
来源:互联网 发布:java宿舍管理系统 编辑:程序博客网 时间:2024/05/17 06:38
1、union
“联合”是一种特殊的类,也是一种构造类型的数据结构。在一个“联合”内可以定义多种不同的数据类型, 一个被说明为该“联合”类型的变量中,允许装入该“联合”所定义的任何一种数据,这些数据共享同一段内存,已达到节省空间的目的(还有一个节省空间的类型:位域)。 这是一个非常特殊的地方,也是联合的特征。另外,同struct一样,联合默认访问权限也是公有的,并且,也具有成员函数。
“联合”是一种特殊的类,也是一种构造类型的数据结构。在一个“联合”内可以定义多种不同的数据类型, 一个被说明为该“联合”类型的变量中,允许装入该“联合”所定义的任何一种数据,这些数据共享同一段内存,已达到节省空间的目的(还有一个节省空间的类型:位域)。 这是一个非常特殊的地方,也是联合的特征。另外,同struct一样,联合默认访问权限也是公有的,并且,也具有成员函数。
2、struct与union
struct与union有一些相似之处。但两者有本质上的不同。在结构中各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和(空结构除外,同时不考虑边界调整)。而在“联合”中,各成员共享一段内存空间, 一个联合变量的长度等于各成员中最长的长度。应该说明的是, 这里所谓的共享不是指把多个成员同时装入一个联合变量内, 而是指该联合变量可被赋予任一成员值,但每次只能赋一种值, 赋入新值则冲去旧值。
struct与union有一些相似之处。但两者有本质上的不同。在结构中各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和(空结构除外,同时不考虑边界调整)。而在“联合”中,各成员共享一段内存空间, 一个联合变量的长度等于各成员中最长的长度。应该说明的是, 这里所谓的共享不是指把多个成员同时装入一个联合变量内, 而是指该联合变量可被赋予任一成员值,但每次只能赋一种值, 赋入新值则冲去旧值。
3.使用注意事项
1)联合里面那些东西不能存放?
我们知道,联合里面的东西共享内存,所以静态、引用都不能用,因为他们不可能共享内存。
2)类可以放入联合吗?
我们先看一个例子:
我们知道,联合里面的东西共享内存,所以静态、引用都不能用,因为他们不可能共享内存。
2)类可以放入联合吗?
我们先看一个例子:
class Test{ public: Test():data(0) { } private: int data; }; typedef union _test { Test test; }UI;
编译通不过,为什么呢?
因为联合里不允许存放带有构造函数、析够函数、复制拷贝操作符等的类,因为他们共享内存,编译器无法保证这些对象不被破坏,也无法保证离开时调用析够函数。
因为联合里不允许存放带有构造函数、析够函数、复制拷贝操作符等的类,因为他们共享内存,编译器无法保证这些对象不被破坏,也无法保证离开时调用析够函数。
3)又是匿名惹的祸??
我们先看下一段代码:
class test{ public: test(const char* p); test(int in); const operator char*() const {return data.ch;} operator long() const {return data.l;} private: enum type {Int, String }; union { const char* ch; int i; }datatype; type stype; test(test&); test& operator=(const test&);}; test::test(const char *p):stype(String),datatype.ch(p){ } test::test(int in):stype(Int),datatype.l(i) {}
看出什么问题了吗?呵呵,编译通不过。为什么呢?难道datatype.ch(p)和datatype.l(i)有问题吗?
让我们来看看构造test对象时发生了什么,当创建test对象时,自然要调用其相应的构造函数,在构造函数中当然要调用其成员的构造函数,所以其要去调用datatype成员的构造函数,但是他没有构造函数可调用,所以出
让我们来看看构造test对象时发生了什么,当创建test对象时,自然要调用其相应的构造函数,在构造函数中当然要调用其成员的构造函数,所以其要去调用datatype成员的构造函数,但是他没有构造函数可调用,所以出
错。
注意了,这里可并不是匿名联合!因为它后面紧跟了个data!
注意了,这里可并不是匿名联合!因为它后面紧跟了个data!
4)如何有效的防止访问出错?
使用联合可以节省内存空间,但是也有一定的风险:通过一个不适当的数据成员获取当前对象的值!例如上面的ch、i交错访问。
为了防止这样的错误,我们必须定义一个额外的对象,来跟踪当前被存储在联合中的值得类型,我们称这个额外的对象为:union的判别式。
一个比较好的经验是,在处理作为类成员的union对象时,为所有union数据类型提供一组访问函数。
5)内存对齐问题.
暂不述.整理资料后,再发.
4.使用.
1.创建别名,在程序中经常会用到将一个数据类型强制转换为另一个类型,这个操作可以使用联合来代替。
比如
typedef union{char c;uint32 u;}CharOfUnion v;可以通过v.u来操作一个uint32类型的对象,当需要将uint32变量的低端字节看做一个字符的时候,只需要访问v.c就可以了。
实际应用中,大多数的协议结构定义中,都会使用union类型来定义。
2、使用联合来将较大的对象分解成组成这个对象的各个字节。
typedef union{uint u;char bytes[4];}asBytes composite;可以使用composite.bytes数组来访问composite.u字段的各个字节。
3.大端小端判别
大端:高字节数据在地址较小一端
小端:低字节数据在地址较小一端
BOOL isBigEndian(){ int i = 1; /* i = 0x00000001*/ char c = *(char *)&i; /* 注意不能写成 char c = (char)i; */ return (int )c != i;}如果是little endian字节序的话,那个i = 1;的内存从小到大依次放的是:0x01 0x00 0x00 0x00,如是,按照i的起始地址变成按照char *方式(1字节)存取,即得c = 0x01;
甚至自己可以写大端小端转换函数
4)理解c++类的布局
有如下类:
class Test{public : float getFVal(){ return f;}private : int i; char c; float f;};Test t;不能在类Test中增加代码,给对象中的f赋值7.0f.
方法:
class Test_Cpy{ public : float getVal(){ return f;} float setVal(float f){ this ->f = f;}private : int i; char c; float f;};....int main(){ Test t; union { Test t1, Test_Cpy t2; }test; test.t2.setVal(7.0f); t = test.t1; assert( t.getVal() == 7.0f ); return 0;}说明:因为在增加类的成员函数时候,那个类的对象的布局基本不变。因此可以写一个与Test类一样结构的类Test_Cpy,而多了一个成员函数setVal,再用uinon结构对齐,就可以给私有变量赋值了。(这种方法在有虚机类和虚函数机制时可能失灵,故不可移植)至于详细的讨论,网上有,这个例子在实际中没有用途,只是用来考察这个内存布局的使用而已.
union在操作系统底层的代码中用的比较多,因为它在内存共赏布局上方便且直观。所以网络编程,协议分析,内核代码上有一些用到union都比较好懂,简化了设计。
整理自:
http://blog.csdn.net/feimor/article/details/6858103
http://blog.csdn.net/jiangnanyouzi/article/details/3158702
http://visionsky.blog.51cto.com/733317/151760
0 0
- union关键字
- 关键字union
- Union关键字
- union关键字
- union关键字
- union关键字
- union关键字
- union关键字
- C语言union关键字
- union关键字使用
- C语言union关键字
- C语言union关键字
- C语言union关键字
- C语言union关键字
- SQL union关键字用法
- C语言union关键字
- C语言union关键字
- C语言union关键字
- CMake 2.8.12.1
- YII中整合PHPMAIL邮件类发送邮件
- Linux下TTY与PTY的区别
- wince GPIO 学习
- PHP中替换键名的简易方法
- union关键字
- 关于sqlserver中的pivot和 unpivot
- YII中整合PHPEXCEL进行数据导出功能
- android下Bitmap和base64之间的转换
- Objective-C、C++以及C之间的区别
- 机器视觉LED光源 选择
- 泛型(2)_适配器
- YII中整合PHPEXCEL进行数据导入MYSQL数据库
- ghost系统无法启动