6.3. Unions
Unions don't take long to explain. They are the same as structures, except
that, where you would have written struct before, now you write
union . Everything works the same way, but with one big
exception. In a structure, the members are allocated separate consecutive
chunks of storage. In a union, every member is allocated the same piece of
storage. What would you use them for? Well, sometimes you want a structure
to contain different values of different types at different times but to
conserve space as much as possible. Using a union, it's up to you to keep
track of whatever type you put into it and make sure that you retrieve the
right type at the right time. Here's an example:
#include <stdio.h>
#include <stdlib.h>
main(){
union {
float u_f;
int u_i;
}var;
var.u_f = 23.5;
printf("value is %f\n", var.u_f);
var.u_i = 5;
printf("value is %d\n", var.u_i);
exit(EXIT_SUCCESS);
} Example 6.11
If the example had, say, put a float into the union and then
extracted it as an int, a strange value would have resulted. The two types
are almost certainly not only stored differently, but of different lengths.
The int retrieved would probably be the low-order bits of the
machine representation of a float , and might easily be made up
of part of the mantissa of the float plus a piece of the
exponent. The Standard says that if you do this, the behaviour is
implementation defined (not undefined). The behaviour is defined by the
Standard in one case: if some of the members of a union are structures with
a ‘common initial sequence’ (the first members of each structure have
compatible type and in the case of bitfields are the same
length), and the union currently contains one of them, then the common
initial part of each can be used interchangeably. Oh good.
The C compiler does no more than work out what the biggest member in
a union can be and allocates enough storage (appropriately aligned if
neccessary). In particular, no checking is done to make sure that the right
sort of use is made of the members. That is your task, and you'll soon find
out if you get it wrong. The members of a union all start at the same
address—there is guaranteed to be no padding in front of any of
them.
The most common way of remembering what is in a union is to embed it in
a structure, with another member of the structure used to indicate the type
of thing currently in the union. Here is how it might be used:
#include <stdio.h>
#include <stdlib.h>
/* code for types in union */
#define FLOAT_TYPE 1
#define CHAR_TYPE 2
#define INT_TYPE 3
struct var_type{
int type_in_union;
union{
float un_float;
char un_char;
int un_int;
}vt_un;
}var_type;
void
print_vt(void){
switch(var_type.type_in_union){
default:
printf("Unknown type in union\n");
break;
case FLOAT_TYPE:
printf("%f\n", var_type.vt_un.un_float);
break;
case CHAR_TYPE:
printf("%c\n", var_type.vt_un.un_char);
break;
case INT_TYPE:
printf("%d\n", var_type.vt_un.un_int);
break;
}
}
main(){
var_type.type_in_union = FLOAT_TYPE;
var_type.vt_un.un_float = 3.5;
print_vt();
var_type.type_in_union = CHAR_TYPE;
var_type.vt_un.un_char = 'a';
print_vt();
exit(EXIT_SUCCESS);
} Example 6.12
That also demonstrates how the dot notation is used to access structures
or unions inside other structures or unions. Some current C compilers allow
you to miss bits out of the names of embedded objects provided that they are
not ambiguous. In the example, such an unambiguous name would be
var_type.un_int and the compiler would work out what you meant.
None the less this is not permitted by the Standard.
It is because of unions that structures cannot be compared for equality.
The possibility that a structure might contain a union makes it hard to
compare such structures; the compiler can't tell what the union currently
contains and so wouldn't know how to compare the structures. This sounds
a bit hard to swallow and isn't 100% true—most structures don't contain
unions—but there is also a philosophical issue at stake about just what
is meant by ‘equality’ when applied to structures. Anyhow, the union
business gives the Standard a good excuse to avoid the issue by not
supporting structure comparison.
|
Printer-friendly version
The C Book
This book is published as a matter of historical interest.
Please read the
copyright and disclaimer information.
GBdirect Ltd provides up-to-date training and consultancy in
C,
Embedded C,
C++
and a wide range of
other subjects based on
open standards if you happen to be interested.
|