计算机科学中,union指的是一个包含多种类型或者格式的值,或者数据结构包含这样的值。一些程序语言支持特殊的数据类型——union类型。换句话说,union类型的定义,规定了哪些类型存储在一起。比如,浮点或者长整型。相对于record类型,record类型定义为包含一个float和一个整型。而union则在一个时刻只能体现一种值。

此处提及的untion类型主要指untagged unions.与之相对的是tagged unions.

由于使用上的限制,untagged union类型通常只出现类型不安全的语言,或者以一种不安全的方法使用(C中)。对于tagged union类型来说,他们的优势在于不需要空间来存储tag。

Union和Structure的区别

从内存的角度来说,Union就是一个类,只不过,它所包含的所以的数据成员都在同一个地址上。因此Union对象的大小就是它所包含的数据类型中最大的那个。

而结构,所有的成员存储在连续的内存地址上,结构的大小就是所有成员类型大小的和。

在某些场合下,为了更有效的利用内存空间,程序逻辑必须确保读取的值是最新写的值。不然转型的时候可能会有异常抛出。下图是一个结构和union的内存分配示意图:

                                 +-----+-----+
struct { int a; float b }  gives |  a  |  b  |
                                 +-----+-----+
                                    ^     ^
                                    |     |
                 memory location:  150   154
                                    |
                                    V
                                 +-----+
union { int a; float b }  gives  |  a  |
                                 |  b  |
                                 +-----+

结构主要用在在当对象有多个对象组成,比如由2个整型组成,比如下面的x,y是并列的。

typedef struct {
    int x;           // x and y are separate
    int y;
} tPoint;


Union则用于一个对象可以是任何类型,但是同一时间只能是一种类型,就和type-less存储系统那样。

typedef enum { STR, INT } tType;
typedef struct {
    tType typ;          // typ is separate.
    union {
        int ival;       // ival and sval occupy same memory.
        char *sval;
    }
} tVal;
 

tagged union,也称作variant, variant record, discriminated union。tagged union和untagged union一样,也是一种数据类型,它可以接受多种不同的,但是固定的类型。同时间只有一种类型可以使用。tag 字段显式的表明哪一个在使用。可以认为是一个带有几个"case"的类型。当操作这种类型是,每一个case都要正确的处理。和普通的union类型一样,tagged union也是每个类型重叠使用存储区域。
tagged union在函数式语言中诸如ML和Haskell中是一种重要的类型,有时也称做变体,编译器能验证tagged union中的所有的case,避免类型错误。Tagged union通常和constructor这个概念一起出现。此处constructor不是指类的构造器。constructor生成 tagged union的值,初始化tag值。
tagged union对于untagged union的优势在于访问tagged union是安全的。Untagged union依靠程序逻辑来保证访问是安全的。tagged unions的缺点就是tag需要占据空间。