ALGOL 68 ALGOL 68 has tagged unions, and uses a case clause to distinguish and extract the constituent type at runtime. A union containing another union is treated as the set of all its constituent possibilities, and if the context requires it a union is automatically coerced into the wider union. A union can explicitly contain no value, which can be distinguished at runtime. An example is:
mode node =
union (
real,
int,
string,
void);
node n := "abc";
case n
in (
real r): print(("real:", r)), (
int i): print(("int:", i)), (
string s): print(("string:", s)), (
void): print(("void:", "EMPTY")),
out print(("?:", n))
esac The syntax of the C/C++ union type and the notion of casts was derived from ALGOL 68, though in an untagged form.
C/C++ In
C and
C++, untagged unions are expressed nearly exactly like structures (
structs), except that each data member is located at the same memory address. The data members, as in structures, need not be primitive values, and in fact may be structures or even other unions. C++ (since
C++11) also allows for a data member to be any type that has a full-fledged constructor/destructor and/or copy constructor, or a non-trivial copy assignment operator. For example, it is possible to have the standard C++
string as a member of a union. The primary use of a union is allowing access to a common location by different data types, for example hardware input/output access, bitfield and word sharing, or
type punning. Unions can also provide low-level
polymorphism. However, there is no checking of types, so it is up to the programmer to be sure that the proper fields are accessed in different contexts. The relevant field of a union variable is typically determined by the state of other variables, possibly in an enclosing struct. One common C programming idiom uses unions to perform what C++ calls a
reinterpret_cast, by assigning to one field of a union and reading from another, as is done in code which depends on the raw representation of the values. A practical example is the
method of computing square roots using the IEEE representation. This is not, however, a safe use of unions in general.
Anonymous union In C++,
C11, and as a non-standard extension in many compilers, unions can also be anonymous. Their data members do not need to be referenced, are instead accessed directly. They have some restrictions as opposed to traditional unions: in C11, they must be a member of another structure or union, and in C++, they can not have
methods or access specifiers. Simply omitting the class-name portion of the syntax does not make a union an anonymous union. For a union to qualify as an anonymous union, the declaration must not declare an object. Example: union { float f; uint32_t d; // Assumes float is 32 bits wide }; f = 3.14f; printf("Hexadecimal representation of 3.14f: %x\n", u.d); Anonymous unions are also useful in C struct definitions to provide a sense of namespacing.
Transparent union In compilers such as GCC, Clang, and IBM XL C for AIX, a attribute is available for union types. Types contained in the union can be converted transparently to the union type itself in a function call, provided that all types have the same size. It is mainly intended for function with multiple parameter interfaces, a use necessitated by early Unix extensions and later re-standardisation.
COBOL In
COBOL, union data items are defined in two ways. The first uses the (66 level) keyword, which effectively maps a second alphanumeric data item on top of the same memory location as a preceding data item. In the example code below, data item is defined as a group containing another group and a numeric data item. is defined as an alphanumeric data item that renames , treating the data bytes continued within it as character data. 01 PERSON-REC. 05 PERSON-NAME. 10 PERSON-NAME-LAST PIC X(12). 10 PERSON-NAME-FIRST PIC X(16). 10 PERSON-NAME-MID PIC X. 05 PERSON-ID PIC 9(9) PACKED-DECIMAL. 01 PERSON-DATA RENAMES PERSON-REC. The second way to define a union type is by using the keyword. In the example code below, data item is defined as a 2-byte binary integer containing a version number. A second data item is defined as a two-character alphanumeric variable. Since the second item is
redefined over the first item, the two items share the same address in memory, and therefore share the same underlying data bytes. The first item interprets the two data bytes as a binary value, while the second item interprets the bytes as character values. 01 VERS-INFO. 05 VERS-NUM PIC S9(4) COMP. 05 VERS-BYTES PIC X(2) REDEFINES VERS-NUM
Pascal In
Pascal, there are two ways to create unions. One is the standard way through a variant record. The second is a nonstandard means of declaring a variable as absolute, meaning it is placed at the same memory location as another variable or at an absolute address. While all Pascal compilers support variant records, only some support absolute variables. For the purposes of this example, the following are all integer types: a
byte consists of 8 bits, a
word is 16 bits, and an
integer is 32 bits. The following example shows the non-standard absolute form: var A: Integer; B: array[1..4] of Byte absolute A; C: Integer absolute 0; In the first example, each of the elements of the array B maps to one of the specific bytes of the variable A. In the second example, the variable C is assigned to the exact machine address 0. In the following example, a record has variants, some of which share the same location as others: type Shape = (Circle, Square, Triangle); Dimensions = record case Figure: Shape of Circle: (Diameter: real); Square: (Width: real); Triangle: (Side: real; Angle1, Angle2: 0..360) end;
PL/I In
PL/I the original term for a union was
cell, which is still accepted as a synonym for union by several compilers. The union declaration is similar to the structure definition, where elements at the same level within the union declaration occupy the same storage. Elements of the union can be any data type, including structures and array. Here vers_num and vers_bytes occupy the same storage locations. 1 vers_info union, 5 vers_num fixed binary, 5 vers_bytes pic '(2)A'; An alternative to a union declaration is the DEFINED attribute, which allows alternative declarations of storage, however the data types of the base and defined variables must match. Rust also supports untagged unions using the keyword. The memory layout of unions in Rust is undefined by default, but a union with the attribute will be laid out in memory exactly like the equivalent union in C. Reading the fields of a union can only be done within an function or block, as the compiler cannot guarantee that the data in the union will be valid for the type of the field; if this is not the case, it will result in
undefined behavior. ==Syntax and example==