Unions

A union declares a type whose members all share one piece of storage. A value holds the bytes of one member, and reading any member reads those same bytes as that member's type — nothing is converted and nothing is checked. A union records no tag, so the program, or the foreign interface it talks to, is responsible for knowing which member is meaningful.

union  = [ attributes ] [ "pub" ] "union" name "{" [ member { "," member } [ "," ] ] "}"
member = name ":" type
union Bits {
    asFloat: float32,
    asUnsigned: uint32,
    asBytes: uint8[4]
}

Members are separated by commas, unlike struct fields; a ; after a member is expected ',' between union fields before ';'.

Building a union

A union literal names exactly one member and gives its value:

let one = Bits { asFloat: 1.0f32 };

Naming none, or more than one, is an error: union initializer for 'Bits' must select exactly one field, but 2 were provided.

var bits: Bits; declares a union without a value. Writing any one member initializes it, and from then on every member may be read.

Reading and writing members

Members are read and written with ., like struct fields. Every member starts at the same address, so a write through one member is seen through all the others, reinterpreted:

let one = Bits { asFloat: 1.0f32 };
PrintLine("{:x}", one.asUnsigned);   // 3f800000, the bit pattern of 1.0
PrintLine("{}", one.asBytes[3]);     // 63, its high byte on a little-endian target

var bits = Bits { asUnsigned: 0x40000000u32 };
PrintLine("{}", bits.asFloat);       // 2.0
bits.asBytes[3] = 0x3Fu8;
PrintLine("{}", bits.asFloat);       // 0.5

Reading a member other than the one last written is not an error; it is the reason a union exists. The result depends on the target's byte order and on the members' representations, so code that relies on it is code about a particular layout.

A member narrower than the union leaves the rest of the storage as it was: writing a uint8 member of a union that also holds a uint64 changes only the low byte.

Layout

A union is as large as its largest member, rounded up to its alignment, and as aligned as its most-aligned member. sizeof(Bits) is 4. See Memory layout.

A union is a value: assigning it copies its bytes, and the copy is independent of the original.

No ownership

A union does not know which member it holds, so it never runs a destructor for any member. A member whose type has a destructor is stored without it ever running; keep such values out of unions, or destroy them by hand.

When to use a union

UseInstead
A C union in a foreign interface—
Examining the bits of a value of another type—
One of several alternatives, known by the compilera variant, whose tag is checked by match
A value of one of several typesa sum type

See also