Я думаю, вы неправильно понимаете Союзы.
Идея использования союзов заключается в том, чтобы сэкономить память ...
да, это одна из причин
... и получить результат, эквивалентный структуре ...
нет
нет
это не эквивалентно. Они похожи в исходном коде, но это совсем другое. Как яблоки и самолеты.
Союзы - это очень, очень низкоуровневая конструкция, которая позволяет вам видеть часть памяти, как будто хранит любой из ее "членов", но вы можете использовать только по одному . Даже использование слова «участник» вводит в заблуждение. Их следует называть «представлениями» или чем-то, а не членами.
Когда вы пишете:
union ABCunion
{
int a;
double b;
char c;
} myAbc;
Вы говорите: «возьмите кусок памяти, достаточно большой для наибольшего числа из числа int, char и double, и давайте назовем его myAbc .
В этой памяти теперь вы можете хранить или int, или double, или char. Если вы храните int, а затем сохраняете double, int исчезает навсегда.
Какой смысл тогда?
Существует два основных варианта использования Союзов.
а) Дискриминационное хранилище
Это то, что мы сделали выше. Я выбираю кусок памяти и придаю ему разные значения в зависимости от контекста. Иногда контекст является явным (вы сохраняете некоторую переменную, которая указывает, какой «тип» переменной вы сохранили), а иногда он может быть неявным (основываясь на разделе кода, вы можете сказать, какой из них должен использоваться). В любом случае, код должен быть в состоянии понять это, или вы не сможете сделать что-нибудь разумное с переменной.
Типичным (явным) примером будет:
struct MyVariantType
{
int typeIndicator ; // type=1 -> It's an int,
// type=2 -> It's a double,
// type=3 -> It's a char
ABCunion body;
};
Например, "Варианты" VB6 - это Союзы, не отличающиеся от вышеупомянутых (но более сложные).
б) Разделенное представление
Это иногда полезно, когда вам нужно видеть переменную как «целое» или как комбинацию частей. Это проще объяснить на примере:
union DOUBLEBYTE
{
struct
{
unsigned char a;
unsigned char b;
} bytes;
short Integer;
} myVar;
Вот короткое int, объединенное с парой байтов. Теперь вы можете просмотреть то же значение, что и короткое int (myVar.Integer), или вы можете так же легко изучить отдельные байты, которые составляют часть значения (myVar.bytes.a и myVar.bytes.b).
Обратите внимание, что это второе использование не переносимо (я уверен); это означает, что не гарантируется работа на разных архитектурах машин; но это использование абсолютно необходимо для задач, для которых был разработан язык C (реализация ОС).