При объединении вы должны использовать только один из элементов, поскольку все они хранятся в одном месте. Это делает его полезным, когда вы хотите сохранить что-то, что может быть одного из нескольких типов. С другой стороны, структура имеет отдельную ячейку памяти для каждого из своих элементов, и все они могут использоваться одновременно.
Чтобы привести конкретный пример их использования, я некоторое время назад работал над интерпретатором Scheme и по существу накладывал типы данных Scheme на типы данных C. Это включало сохранение в структуре перечисления, указывающего тип значения, и объединения для хранения этого значения.
union foo {
int a; // can't use both a and b at once
char b;
} foo;
struct bar {
int a; // can use both a and b simultaneously
char b;
} bar;
union foo x;
x.a = 3; // OK
x.b = 'c'; // NO! this affects the value of x.a!
struct bar y;
y.a = 3; // OK
y.b = 'c'; // OK
edit: Если вам интересно, что установка x.b на 'c' меняет значение x.a на, технически говоря, оно не определено. На большинстве современных машин значение char составляет 1 байт, а int - 4 байта, поэтому, давая x.b значение 'c', вы получаете первый байт x.a того же значения:
union foo x;
x.a = 3;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);
печать
99, 99
Почему эти два значения одинаковы? Поскольку последние 3 байта int 3 равны нулю, поэтому он также читается как 99. Если мы введем большее число для x.a, вы увидите, что это не всегда так:
union foo x;
x.a = 387439;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);
печать
387427, 99
Чтобы ближе познакомиться с фактическими значениями памяти, давайте установим и распечатаем значения в шестнадцатеричном виде:
union foo x;
x.a = 0xDEADBEEF;
x.b = 0x22;
printf("%x, %x\n", x.a, x.b);
печать
deadbe22, 22
Вы можете ясно видеть, где 0x22 переписал 0xEF.
НО
В C порядок байтов в int не определен. Эта программа перезаписала 0xEF с 0x22 на моем Mac, но есть другие платформы, где вместо этого перезаписывается 0xDE, потому что порядок байты, составляющие int, были обращены. Поэтому при написании программы никогда не следует полагаться на поведение перезаписи определенных данных в объединении, поскольку оно не переносимо.
Для получения дополнительной информации о порядке байтов, проверьте endianness .