Names specified here
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 doubles. (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:
  . . . // Access alias3.t1
  break;
case TYPE2:
  . . . // Access alias3.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

CHaR
Sitemap Supported
Site format updated 2024-06-05T22:37:07.391+0000
Data updated 1970-01-01T00:00:00.000+0000
Page updated 2022-06-17T21:43:05.000+0000