C语言中union联合体存在的意义
共用体是什么?
如上图所示,共用体正如“共有”关键字所描述的一样,共用体所占的数据空间是共用体中最大的数据类型成员所占用的空间,这些成员并不是随意放置,而是用有相同的首地址。因此,我们在任意时刻只可以按照一个数据类型对共用体进行赋值,共用体中这些成员的关系是“或”,即“不是你死就是我活”。
其实我们可以这样说“共用体其实可以在任意时刻被当作其任意一个数据成员来赋值使用”。共用体的出现基本上实现了我们追求的“万能数据类型”。
共用体与结构体的区别
我们看到数据成员在结构体数据内存存储中是顺序排列的,因此结构体完成的是数据成员的“和”操作,相反我们看union联合体则是完成的是数据成员之间的“与“操作。
联合体应用实例
题目要求:我们要用链表来存储老师和学生的成员信息,当老师录入信息时,我们只需要老师的性别;而学生录入信息时,我们只需要学生的学号。
例程实现:
#include <iostream>
#include <string>
using namespace std;
union sub_infor // 可以作为char类型来使用,也可以作为int类型来使用
{
char sex;
int StudNum;
};
struct MumberInfor
{
union sub_infor infor;
char Kind;
struct MumberInfor* M_infor;
friend istream& operator >> (istream& cin, MumberInfor& Object);
friend ostream& operator << (ostream& cout, MumberInfor& Object);
};
istream& operator >> (istream& cin, MumberInfor& Object)
{
cout << "请输入成员类别(t:teacher;s:student):";
cin >> Object.Kind;
if (Object.Kind != 't' && Object.Kind != 's')
{
cout << "输入成员类别非法" << endl;
exit(-1); // 看见错误代码为-1就知道输入类别非法
}
if (Object.Kind == 't')
{
cout << "请输入老师性别(f:女;m:男):";
cin >> Object.infor.sex;
if (Object.infor.sex != 'f' && Object.infor.sex != 'm')
{
cout << "输入老师性别非法" << endl;
exit(-2); // 看见错误代码为-2就知道输入性别非法
}
}
else if (Object.Kind == 's')
{
cout << "请输入学生学号(整型变量):";
cin >> Object.infor.StudNum;
}
return cin;
}
ostream& operator << (ostream& cout, MumberInfor& Object)
{
if (Object.Kind == 't')
{
cout << "老师的性别为" << (Object.infor.sex == 'f' ? "女" : "男");
}
else if (Object.Kind == 's')
{
cout << "学生的学号为" << Object.infor.StudNum;
}
return cout;
}
struct MumberInfor* DynamicApplySpace()
{
MumberInfor *head, *current, *tail;
int i = 0;
head = new MumberInfor;
tail = head;
while (1)
{
current = new MumberInfor;
cin >> *current;
tail->M_infor = current;
tail = current;
cout << "是否停止录入(1:YES,0:NO):";
cin >> i;
if (i)
{
break;
}
}
tail->M_infor = NULL;
return head;
}
void Print_LinkedList(struct MumberInfor* head)
{
struct MumberInfor* current = head;
cout << *head << endl;
while (current->M_infor != NULL)
{
current = current->M_infor;
cout << *current << endl;
}
}
void FreeHeapMemory(struct MumberInfor* head)
{
struct MumberInfor *current = head, *next;
while (current->M_infor != NULL)
{
next = current->M_infor;
free(current);
current = next;
}
}
int main()
{
struct MumberInfor* head;
head = DynamicApplySpace(); // 动态申请内存
Print_LinkedList(head); // 输出链表数据
FreeHeapMemory(head); // 释放堆区内存
}
代码优化:
我们对代码做如下优化,自动判断输入数据的数据类型,然后指出应该输入的数据类型。
#include <iostream>
#include <string>
using namespace std;
union sub_infor
{
char sex;
int StudNum;
};
struct MumberInfor
{
union sub_infor infor;
char Kind;
struct MumberInfor* M_infor;
friend istream& operator >> (istream& cin, MumberInfor& Object);
friend ostream& operator << (ostream& cout, MumberInfor& Object);
};
istream& operator >> (istream& cin, MumberInfor& Object)
{
cout << "请输入成员类别(t:teacher;s:student):";
cin >> Object.Kind;
if (typeid(Object.Kind).name() == "char" && Object.Kind != 't' && Object.Kind != 's') // 将输入数据类型的判断纳入非法检测当中
{
cout << "输入成员类别非法" << endl;
exit(-1); // 看见错误代码为-1就知道输入类别非法
}
if (Object.Kind == 't')
{
cout << "请输入老师性别(f:女;m:男):";
cin >> Object.infor.sex;
if (typeid(Object.infor.sex).name() == "char" && Object.infor.sex != 'f' && Object.infor.sex != 'm') // 将输入数据类型的判断纳入非法检测当中
{
cout << "输入老师性别非法" << endl;
exit(-2); // 看见错误代码为-2就知道输入性别非法
}
}
else if (Object.Kind == 's')
{
cout << "请输入学生学号(整型变量):";
cin >> Object.infor.StudNum;
}
return cin;
}
ostream& operator << (ostream& cout, MumberInfor& Object)
{
if (Object.Kind == 't')
{
cout << "老师的性别为" << (Object.infor.sex == 'f' ? "女" : "男");
}
else if (Object.Kind == 's')
{
cout << "学生的学号为" << Object.infor.StudNum;
}
return cout;
}
struct MumberInfor* DynamicApplySpace()
{
MumberInfor *head, *current, *tail;
int i = 0;
head = new MumberInfor;
tail = head;
while (1)
{
current = new MumberInfor;
cin >> *current;
tail->M_infor = current;
tail = current;
cout << "是否停止录入(1:YES,0:NO):";
cin >> i;
if (i)
{
break;
}
}
tail->M_infor = NULL;
return head;
}
void Print_LinkedList(struct MumberInfor* head)
{
struct MumberInfor* current = head;
cout << *head << endl;
while (current->M_infor != NULL)
{
current = current->M_infor;
cout << *current << endl;
}
}
void FreeHeapMemory(struct MumberInfor* head)
{
struct MumberInfor *current = head, *next;
while (current->M_infor != NULL)
{
next = current->M_infor;
free(current);
current = next;
}
}
int main()
{
struct MumberInfor* head;
head = DynamicApplySpace();
Print_LinkedList(head);
FreeHeapMemory(head);
}
联合体成员的访问方式
// 定义union联合体变量
union sub_infor // 联合体定义
{
char sex;
int StudNum;
};
// 在使用联合体变量成员数据时,联合体成员访问方法
sub_infor.sex
sub_infor.StudNum
输入数据的类型检测
int i = 0; // 定义变量
cin >> i; // 输入变量
if(typeid(i).name() == "int") // typeid(var_name).name()返回的是字符串类型的常量,即”int”,”float”,”char”,”string”……等数据类型名
{
cout << "输入数据类型错误" << endl;
}