共用体(union)是一种数据格式,它能够存储不同的数据类型,但只能同时存储其中的一种类型。也就是说,结构可以同时存储int、long和double,共用体只能存储int、long或double。共用体的句法与结构相似,但含义不同。例如:
union one4all {
int int_val;
long long_val;
double double_val;
};
可以使用one4all变量来存储int、long或double,条件是在不同的时间进行:
one4all pail;
pail.int_val = 15;
cout << pail.int_val << endl;
pail.double_val = 1.38;
cout << pail.double_val << endl;
上方代码表示,当我们将pail里的int_val赋值时,pail存储的是int类型的变量,因此long和double的变量失效,同理当我们将pail里的double_val赋值时,pail存储的是double类型的变量。
由于共用体每次只能存储一个值,因此它必须有足够的空间存储空间占用最大的成员,所以,公用体的长度为其空间占用最大成员的长度。
公用体的用途之一:当数据项使用两种或更多种格式(但不会同时使用)时,可节省空间。例如,假设管理一个小商品目录,其中有些商品的id是整数,另一些id是字符串的时候。
struct widget {
char name[20];
int type;
union id {
int id_int;
char id_char[20];
}id_val;
}prize;
int main() {
cin >> prize.name >> prize.type;
if (prize.type == 1) cin >> prize.id_val.id_int;
else cin >> prize.id_val.id_char;
return 0;
}
其中,上述代码的公用体可用匿名共用体代替。
struct widget {
char name[20];
int type;
union {
int id_int;
char id_char[20];
};
}prize;
int main() {
cin >> prize.name >> prize.type;
if (prize.type == 1) cin >> prize.id_int;
else cin >> prize.id_char;
return 0;
}
由于共用体是匿名的,因此id_int和id_char被视为prize的两个成员,它们的地址相同,所以不需要中间标识符id_val。程序员负责确定当前哪个成员是活动的。
共用体常用于(但并非只能用于)节省内存,操作系统数据结构或硬件数据结构。
C++的enum工具提供了另一种创建符号常量的方式,这种方式可以代替const。它还允许定义新类型,但必须按严格的限制进行。使用enum的句法与使用结构相似。例如:
enum spectrum{red,orange,yellow,green,blue,violet,indigo,ultraviolet};
这条语句完成两项工作:
enum bits { one = 1, two = 2, four = 4, eight = 8 };
指定的值必须是整数,也可以只显式地定义其中一些枚举量的值:
enum bits { zero, null = 0, one, numero_uno = 1 };
其中,zero和null都为0,one和numero_uno都为1。在C++早期的版本中,只能将int值(或提升为int的值)赋给枚举量,但这种限制取消了,因此可以使用long甚至long long类型的值。
可以用枚举名来声明这种类型的变量,例如上述的spectrum:
spectrum band
在不进行强制类型转换的情况下,只能将定义枚举时使用的枚举量赋给这种枚举的变量:
band = blue; //valid, blue is an enumerator
band = 2000; //invalid,2000not an enumerator
因此,spectrum变量受到限制,只有8个可能的值。如果试图将一个非法值赋给它,则有些编译器将出现编译器错误,而另一些则发出警告。为获得最大限度的可移植性,应将把非enum值赋给enum变量视为错误。
对于枚举,只定义了赋值运算符。具体地说,没有为枚举定义算术运算:
band = orange; //valid
++band; //not valid
band = orange + red; //not valid,but a litter tricky
其中band = orange + red非法原因是因为没有为枚举定义运算符,但用于算数表达式中时,枚举将被转换为整数,因此表达式orange+red将被转换为1+0。这是一个合法的表达式,但因为得到的答案类型为int,因此不能将其赋给类型为spectrum的变量band
枚举量是整型,可被提升为int类型,但int类型不能自动转换为枚举类型:
int color = blue; //valid,spectrum type promoted to int
band = 3; //invalid,int not converted to spectrum
color = 3 + red; //valid,red converted to int
如果int值是有效的,则可以通过强制类型转换,将它赋给枚举变量:
band = spectrum(3);
枚举的取值范围:最初,对于枚举来说,只有声明中指出的那些值是有效的。然而,C++现在通过强制类型转换,增加了可赋给枚举变量的合法值。每个枚举都有取值范围,通过强制类型转换,可以将取值范围中的任何整数值赋给枚举变量,即使这个值不是枚举值。例如:
enum bits { one = 1, two = 2, four = 4, eight = 8 };
bits myflag;
myflag = bits(6);
其中6不是枚举值,但它位于枚举定义的取值范围内。
取值范围的定义如下:首先要找出上限,需要知道枚举量的最大。找到大于这个最大值的、最小的2的幂,将它减去1,得到的便是取值范围的上限。要知道下限,需要知道枚举量的最小值。如果它不小于0,则下限为0;否则,采用与寻找上限一样的方法。
声明:以上整理自个人理解和Stephen Prata 著的《C++ Primer Plus》