Name | Description | Notes | Source | Availability | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|
union |
Introduces union type | L | Keyword | C89 | C90 | C95 | C99 | C11 |
C allows groups of objects to share the same area of
memory so long as only one object occupies it at a time. Such
an area is called a union, and it is declared with
the keyword union
. For
example, the variable var
below is
declared to hold either an int
, a
double
or a
float
, which
are members of the union, called si
, d
and f
respectively:
union { int si; double d; float f; } var;
Members can be of any complete type. They are accessed using the
operator .
:
printf("%d\n", var.si); var.d = 10.4;
Under most circumstances, the only member that can be read is the one last written to. There is no intrinsic way to determine which member is currently in use, so the program must define a way to determine that separately. In practice, the programmer has usually already defined this mechanism before determining that a union is required.
There are a few cases where writing one member and then
reading another makes sense. One is where you need to examine
the underlying representation of a type T
:
union { T foo; unsigned char raw[sizeof(T foo)]; } alias1;
Another case is when you want to access the internal parts of a type whose representation is known, such as a complex type:
union { double complex foo; double parts[2]; } alias2;
The representation of double complex
is, by
definition, an array of
two double
s. (Note,
however, that functions and macros like creal
, cimag
and CMPLX
can obviate the technique in
this case.)
When a union's members are structures beginning with fields of the same type, those fields can be accessed through any member:
struct hdr { int type; }; struct type1 { int type; char name[60]; }; struct type2 { int type; ipaddr_t addr; unsigned port; }; union { struct hdr h; struct type1 t1; struct type2 t2; } alias3; enum { UNK, TYPE1, TYPE2 }; alias3.t1.type = TYPE1; strncpy(alias3.t1.name, "foo", sizeof alias3.t1.name); switch (alias3.h.type) { case TYPE1: . . . // Accessalias3.t1
break; case TYPE2: . . . // Accessalias3.t2
break; };
The types of var
, alias1
, alias2
and
alias3
above are anonymous union
types, but unions are syntactically almost identical to
structures, so you
can define a named union type:
union basic { int si; double d; float f; };
…define a type alias for a union type:
typedef union { int si; double d; float f; } basic_union;
…or declare an incomplete union type:
union basic;
An incomplete type is sufficient to declare something that uses pointers to the union type:
void do_something(union basic *box);
…because a pointer type is always complete, even if it points to something incomplete.
From C11, when a union appears as a member of a structure, the member itself can be anonymous:
struct { int x; union basic; int y; } foo;
Although the members si
,
d
and f
are
semantically only indirect members of foo
, they appear as direct members syntactically,
as foo.si
, foo.d
and foo.f
.
- type-specifier
struct-or-union-specifier
- struct-or-union-specifier
struct-or-union identifieropt { struct-declaration-list }
struct-or-union identifier
- struct-or-union
union
- struct-declaration-list
struct-declaration
struct-declaration-list struct-declaration
- struct-declaration
specifier-qualifier-list struct-declarator-listopt ;
-
static_assert-declaration
since C11 - specifier-qualifier-list
type-specifier specifier-qualifier-listopt
type-qualifier specifier-qualifier-listopt