我以前很轻松地使用过工会;今天,当我读这篇文章时,我感到震惊,并知道这段代码
union ARGB
{
uint32_t colour;
struct componentsTag
{
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
} components;
} pixel;
pixel.colour = 0xff040201; // ARGB::colour is the active member from now on
// somewhere down the line, without any edit to pixel
if(pixel.components.a) // accessing the non-active member ARGB::components
实际上是未定义的行为,即从工会成员中读取除最近写的人以外的内容会导致未定义的行为。如果这不是联合的预期用途,那么什么才是?谁能详细解释一下吗?
更新:
我想事后澄清一些事情。
如果一个标准布局联合包含几个共享一个公共初始序列的标准布局结构,并且如果这个标准布局联合类型的对象包含一个标准布局结构,则允许检查任何标准布局结构成员的公共初始序列。§9.2/19:两个标准布局结构共享一个公共的初始序列,如果对应的成员具有布局兼容的类型,并且两个成员都不是位域,或者对于一个或多个初始成员的序列,两个都是具有相同宽度的位域。
李< /引用> < / >- 而在C中,(C99 tc3 - Dr 283起)这样做是合法的(感谢Pascal Cuoq用于提出这个问题)。然而,尝试执行它仍然可能导致未定义的行为,如果读取的值恰好是被读取的类型的无效值(所谓的“陷阱表示”)。否则,读取的值是实现定义的。
C89/90在未指定的行为(附件J)和K&R的书中说它是定义的实现。引用K&R:
这就是联合的目的——一个单一变量,可以合法地保存几种类型中的任何一种。[…]只要使用一致:检索的类型必须是最近存储的类型。程序员有责任跟踪当前存储在联合中的类型;如果将某些内容存储为一种类型并提取为另一种类型,则结果是依赖于实现的。
李< /引用> < / >从Stroustrup的tc++ PL提取(强调我)
使用联合对于数据的兼容性至关重要[…]有时被误用为“类型转换””。
李< /引用> < / >
例如:使用继承来实现代码重用当然是c++标准所允许的,但是这并不是将继承引入c++语言特性的目的或初衷. C。这就是为什么安德烈的回答仍然被人们所接受的原因。