本标准回答C++标准第9.5节,或C99标准第6.5.2.3节第5段(或C11标准第6段,或C18标准第6.7.2.1节第16段)中的所有问题:
在联合中,任何时候最多只能有一个数据成员处于活动状态,也就是说,任何时候最多有一个数据成员的值可以存储在联合中.[注意:为了简化联合的使用,有一个特殊的保证:如果POD联合包含几个共享公共初始序列(9.2)的POD struct ,并且如果此POD联合类型的对象包含其中一个POD struct ,则允许判断任何POD struct 成员的公共初始序列;参见9.2.]联合的大小足以包含其最大的数据成员.每个数据成员的分配就像它是 struct 的唯一成员一样.
这意味着每个成员共享相同的内存区域.最多有is个成员处于活动状态,但您无法找到哪一个.您必须将有关当前活动成员的信息存储到其他地方.除了联合存储这样一个标志(例如,有一个 struct ,其中一个整数作为类型标志,一个联合作为数据存储)将为您提供一个所谓的"有区别的联合":一个知道它当前是什么类型的联合.
一种常见的用法是在词法分析器中,您可以有不同的标记,但是根据标记的不同,要存储的信息也不同(将line
放入每个 struct 中以显示公共初始序列是什么):
struct tokeni {
int token; /* type tag */
union {
struct { int line; } noVal;
struct { int line; int val; } intVal;
struct { int line; struct string val; } stringVal;
} data;
};
标准允许您访问每个成员的line
个,因为这是每个成员的公共初始序列.
存在允许访问所有成员的编译器扩展,而不管哪个成员当前存储了它的值.这允许高效地重新解释每个成员之间具有不同类型的存储比特.例如,以下内容可用于将一个浮点变量分解为2个无符号短码:
union float_cast { unsigned short s[2]; float f; };
这在编写低级代码时非常方便.如果编译器不支持该扩展,但您仍然支持它,那么您将编写结果未定义的代码.所以,如果你使用这个技巧,一定要确保你的编译器支持它.