联合(union)在C/C++里面见得并不多,但是在一些对内存要求特别严格的地方,联合又是频繁出现,那么究竟什么是联合、怎么去用、有什么需要注意的地方呢?就这些问题,我试着做一些简单的回答,里面肯定还有不当的地方,欢迎指出!
1、什么是联合?
“联合”是一种特殊的类,也是一种构造类型的数据结构。 在一个“联合”内可以定义多种不同的数据类型, 一个被说明为该“联合”类型的变量中,允许装入该“联合”所定义的任何一种数据,这些数据共享同一段内存,已达到节省空间的目的(还有一个节省空间的类型:位域)。 这是一个非常特殊的地方,也是联合的特征。另外,同struct一样,联合默认访问权限也是公有的,并且,也具有成员函数。
2、联合与结构的区别?
“联合”与“结构”有一些相似之处。但两者有本质上的不同。在结构中各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和(空结构除外,同时不考虑边界调整)。而在“联合”中,各成员共享一段内存空间, 一个联合变量的长度等于各成员中最长的长度。应该说明的是, 这里所谓的共享不是指把多个成员同时装入一个联合变量内, 而是指该联合变量可被赋予任一成员值,但每次只能赋一种值, 赋入新值则冲去旧值。
3、如何定义?
例如:
union test
{
test() { }
int office;
char teacher[5];
};
定义了一个名为test的联合类型,它含有两个成员,一个为整型,成员名为office;另一个为字符数组,数组名为teacher。联合定义之后,即可进行联合变量说明,被说明为test类型的变量,可以存放整型量office或存放字符数组teacher。
4、如何说明?
联合变量的说明有三种形式:先定义再说明、定义同时说明和直接说明。
以test类型为例,说明如下:
1) union test
{
int office;
char teacher[5];
};
union test a,b; /*说明a,b为test类型*/
2) union test
{
int office;
char teacher[5];
} a,b;
3) union
{
int office;
char teacher[5];
} a,b;
经说明后的a,b变量均为test类型。
a,b变量的长度应等于test的成员中最长的长度,即等于teacher数组的长度,共5个字节。a,b变量如赋予整型值时,只使用了4个字节,而赋予字符数组时,可用5个字节。
5、如何使用?
对联合变量的赋值,使用都只能是对变量的成员进行。
联合变量的成员表示为:联合变量名.成员名
例如,a被说明为test类型的变量之后,可使用a.class、a.office
不允许只用联合变量名作赋值或其它操作,也不允许对联合变量作初始化赋值,赋值只能在程序中进行。
还要再强调说明的是,一个联合变量,每次只能赋予一个成员值。换句话说,一个联合变量的值就是联合变员的某一个成员值。
6、匿名联合
匿名联合仅仅通知编译器它的成员变量共同享一个地址,而变量本身是直接引用的,不使用通常的点号运算符语法.例如:
#include <iostream>
void main()
{
union{
int test;
char c;
};
test=5;
c=''a'';
std::cout<<i<<" "<<c;
}
正如所见到的,联合成分象声明的普通局部变量那样被引用,事实上对于程序而言,这也正是使用这些变量的方式.另外,尽管被定义在一个联合声明中,他们与同一个程序快那的任何其他局部变量具有相同的作用域级别.这意味这匿名联合内的成员的名称不能与同一个作用域内的其他一直标志符冲突.
对匿名联合还存在如下限制:
因为匿名联合不使用点运算符,所以包含在匿名联合内的元素必须是数据,不允许有成员函数,也不能包含私有或受保护的成员。还有,全局匿名联合必须是静态(static)的,否则就必须放在匿名名字空间中。
7、几点需要讨论的地方:
1、联合里面那些东西不能存放?
我们知道,联合里面的东西共享内存,所以静态、引用都不能用,因为他们不可能共享内存。
2、类可以放入联合吗?
我们先看一个例子:
class Test
{
public:
Test():data(0) { }
private:
int data;
};
typedef union _test
{
Test test;
}UI;
编译通不过,为什么呢?
因为联合里不允许存放带有构造函数、析够函数、复制拷贝操作符等的类,因为他们共享内存,编译器无法保证这些对象不被破坏,也无法保证离开时调用析够函数。
8、又是匿名惹的祸??
我们先看下一段代码:
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成员的构造函数,但是他没有构造函数可调用,所以出错。
注意了,这里可并不是匿名联合!因为它后面紧跟了个data!
9、如何有效的防止访问出错?
使用联合可以节省内存空间,但是也有一定的风险:通过一个不适当的数据成员获取当前对象的值!例如上面的ch、i交错访问。
为了防止这样的错误,我们必须定义一个额外的对象,来跟踪当前被存储在联合中的值得类型,我们称这个额外的对象为:union的判别式。
一个比较好的经验是,在处理作为类成员的union对象时,为所有union数据类型提供一组访问函数。
分享到:
相关推荐
【C/C++笔试题】 在C/C++编程中,面试或笔试经常涉及到各种技术细节,以下是一些重要的知识点: 1. **入口点**:在Windows程序中,入口点通常是`WinMain()`函数,而非传统的`main()`。这个函数是Windows API的一...
5. 最终结果:将四个32位的寄存器(A,B,C,D)联合起来,生成一个128-bits的散列值。 在逆向工程和网络协议分析中,MD5算法可以用来加密和解密信息,以确保信息的完整性和机密性。同时,MD5算法也可以用于错误...
【C和C++联合调用】是编程领域中常见的需求,特别是在既有C代码又有C++代码的项目中。为了实现这种跨语言的调用,我们需要理解C和C++在编译和链接时的不同处理方式。 C++引入了名称修饰(Name Mangling)机制,它在...
静态对象的引用又因为((a+b) == (c+d))会永远为true而导致错误。所以可选的只剩下返回一个对象了。 6. “引用”与多态的关系? 引用是除指针外另一个可以产生多态效果的手段。这意味着,一个基类的引用可以...
将字符串A变换为字符串B所用的最少字符操作数称为字符串A到B的编辑距离,记为d(A,B)。试设计一个有效算法,对任给的2个字符串A和B,计算出它们的编辑距离d(A,B)。 编程任务: 对于给定的字符串A和B,编程计算其编辑距离d...
- **C库的调用**:当C++程序需要调用C语言编写的库时,需要使用 `extern "C"` 来避免名称修饰(name mangling)导致的链接错误。 - **跨语言调用**:在混合使用C和C++代码的情况下,`extern "C"` 可以确保C++编译器...
在MATLAB中,MEX(MATLAB EXecutable)文件是一种可执行文件,它可以是用C、C++或其他支持的语言编写的,用于加速MATLAB代码的运行。当MATLAB调用MEX文件时,它可以直接与C++代码交互,提高了运行效率。在这个示例中...
### C++ 旅程知识点梳理 #### 一、C/C++中的位域(Bit Fields) ...以上知识点涵盖了C/C++中位域、共用体、链表、大端与小端模式以及枚举类型的基本概念和用法,希望对你在学习C/C++过程中有所帮助。
游戏可兼容C/D/E/F四盘,这意味着游戏设计时考虑到了不同用户硬盘分区的差异,允许玩家将游戏文件放在这些驱动器的根目录下,便于启动和运行。这种跨盘符的兼容性设计显示了开发者对用户使用环境的考虑。 至于标签...
为次,ANSI和ISO的联合委员会于1989年着手为C++制定标准。1994年2月,该委员会出版了第一份非正式草案,1998年正式推出了C++的国际标准。 (二) C和C++ C++是C的超集,也可以说C是C++的子集,因为C先出现。按常理说...
根据给定文件的信息,本文将围绕“2011年联发科技面向硕士研究生计算机专业的C/C++笔试题目及答案”这一主题展开讨论。主要内容包括:C/C++基础知识、算法与数据结构、软件工程概念以及面试技巧等。 ### 一、C/C++...
为了使C++编译器能够识别C语言的函数,在C++中使用C语言函数时需要加上 `extern "C"`。 ```cpp extern "C" { int c_function(); } ``` **4. 缺省参数** 函数可以设置缺省参数值,但要注意,一旦设置了缺省值,...
《C++ Primer》第五版是C++领域内极具权威性的教材,由Stanley B.Lippman, Josée Lajoie, Barbara E.Moo三位专家联合编写。本书覆盖了C++编程语言的各个方面,包括基本概念、程序结构、标准库等,并以示例驱动的...
GG(a,b,c,d,M1,5,0xf61e2562) GG(d,a,b,c,M6,9,0xc040b340) GG(c,d,a,b,M11,14,0x265e5a51) GG(b,c,d,a,M0,20,0xe9b6c7aa) GG(a,b,c,d,M5,5,0xd62f105d) GG(d,a,b,c,M10,9,0x02441453) GG(c,d,a,b,M15,14,0xd8a...
嵌入式C和C++程序员的考试题目涵盖了C语言的基础概念和特性,这些知识点对于理解和编写嵌入式系统代码至关重要。下面将详细解释题目中涉及的一些关键知识点: 1. C语言中最简单的数据类型包括整型(int)、实型...
1. **C++语法基础**:包括但不限于数据类型、控制流程、数组、指针、函数、枚举与联合、文件读写等内容。 2. **程序流程图**:设计出每个程序的详细流程图,便于理解和调试。 3. **Visual C++ IDE的使用**:掌握如何...
例如,类型A包含三个整型成员,类型B包含一个字符型成员、两个整型成员和一个双精度浮点型成员,类型C包含一个字符指针型成员和一个整型数组,类型D包含两个整数指针型成员和一个整型成员,类型E包含一个整型成员、...