C++学习之旅-{共用体一游}
一开始学C语言的时候(初学),对于共用体的概念和用法都很模糊,因为很少去用也没有细细的研究。之后深入学习才揭开共用体的面纱。(相信很多人也和我有相同的经历)
共用体(union)它是一种数据格式,直白的讲它能够存储不同的数据类型,但是只能同时存储其中的一种类型。
//结构
struct online
{
int num;
long phone;
double price;
};
//联合
union online
{
int num;
long phone;
double price;
}
类比结构,我们会发现结构可以同时存储 int、long、double等不同数据类型,但是我们的共用体(联合)只能每次存储其成员中的一个int 或 long 或double。共用体的句法与结构相似但是含义不同。
就比如这个例子:
union online
{
int num;
long phone;
double price;
double stm;
};
我们可以使用online来存储int num、long phone 或者 double price,条件是我们要在不同的时间进行。
online pail;
pail.num = 15;
cout << "pail.num = " << pail.num << endl;
pail.phone = 123456789;
cout << "pail.phone = " << pail.phone << endl;
pail.price = 123.345436;
cout << "pail.price = " << pail.price << endl;
cout << "pail.stm = " << pail.stm << endl;
cout << "pail.num = " << pail.num << endl;
cout << "pail.phone = " << pail.phone << endl;
在我的机器上运行结果如下:
我们可以很清晰的看到,共用体对于不同类型的变量的存储都是可以的,但是每次只能存储一个。及时pail.stm我们没有给它赋值。但是却还是可以打印出和price一样的值。至于pail.num和pail.phone打印出错。是因为double类型的price将共用体的空间占据,然后通过int和long类型的变量对于共用空间进行访问,由于类型的长度等都不同所以访问打印的值也是垃圾值。可以类比price和stm这样同类型的访问。
总结:pail有时可以是int变量,而有时又可以是double变量,成员名称标识了变量的容量。由于共用体每次只能存储一个值,因此它必须有足够的空间来存放最大的成员,所以,共用体的长度取决于其最大成员的长度
#include <iostream>
union online
{
int num;
long phone;
double price;
double stm;
};
int main()
{
using namespace std;
cout << "union online size = " << sizeof(online) << endl;
return 0;
}
打印结果
这里的8是8个字节,因为double是这个共用体中最长的数据类型。如果换成结构体这里可能测得的大小就是24(linux、Uinx)22(windows)至于为什么大家应该都知道。嘿嘿
共用体能够用来做什么?举个例子,当数据项需要两种或者更多的格式(但不会同时使用)时,使用共用体可以节省空间。比如,超市里有管理商品的目录,有的商品id是整数,而有的商名ID是字符串。在这种情况下。我们可以这样做
struct widget
{
char brand[20];
int type;
union id
{
long id_num;
char id_char[20];
}id_val;
};
...
widget prize;
...
/* 根据标志位判断使用何种id。此处id共用可节省空间 */
if (prize.type == 1)
{
cin >> prize.id_val.id_num;
}
else
{
cin >> prize.id_val.id_char;
}
匿名共用体
所谓匿名共用体就是没有名称的共用体。其成员将成为位于相同地址处的变量。显然,每次只有一个成员是当前的成员
同样是上面那个例子
struct widget
{
char brand[20];
int type;
//匿名共用体
union
{
long id_num;
char id_char[20];
};
};
...
widget prize;
...
/* 根据标志位判断使用何种id。此处id共用可节省空间 */
if (prize.type == 1)
{
cin >> prize.id_num;
}
else
{
cin >> prize.id_char;
}
由于共用体是匿名的,因此id_num和id_char被视为prize的两个成员,它们的地址相同,所以不需要用中间标识符id_val.程序负责确定当前哪个成员是活动的。