Как проверить, какой тип в настоящее время используется в объединении?
скажем, мы имеем объединение:
typedef union someunion {
int a;
double b;
} myunion;
Можно ли проверить, какой тип находится в объединении после того, как я установил, например. а = 123?
Мой подход состоит в том, чтобы добавить этот союз к некоторой структуре и установить uniontype в 1, когда он int и 2, когда он удваивается.
typedef struct somestruct {
int uniontype
myunion numbers;
} mystruct;
Есть ли лучшее решение?
Ответы
Ответ 1
Есть ли лучшее решение?
Нет, решение, которое вы показали, является лучшим (и единственным). union
довольно просты - они не "отслеживают" то, что вы назначили для чего. Все, что они делают, это позволяют вам повторно использовать один и тот же диапазон памяти для всех их членов. Они не предоставляют ничего кроме этого, поэтому заключить их в struct
и использовать поле типа для отслеживания - это как раз то, что нужно сделать.
Ответ 2
C автоматически не отслеживает, какое поле в объединении используется в настоящее время. (На самом деле, я считаю, что чтение из "неправильного" поля приводит к определенному поведению реализации.) Таким образом, ваш код должен отслеживать, какой из них в настоящее время используется/заполняется.
Ваш подход к сохранению отдельной переменной uniontype является очень распространенным подходом к этому и должен хорошо работать.
Ответ 3
Невозможно напрямую запросить тип, хранящийся в настоящее время в union
.
Единственные способы узнать тип, хранящийся в union
, - это иметь явный флаг (как в вашем примере mystruct
) или гарантировать, что управление только течет к определенным частям кода, когда объединение имеет известный активный элемент.
Ответ 4
В зависимости от приложения, если это короткоживущий объект, вы можете кодировать тип в потоке управления, то есть. имеют отдельные блоки/функции для обоих случаев
struct value {
const char *name;
myunion u;
};
void throwBall(Ball* ball)
{
...
struct value v;
v.name = "Ball"; v.u.b = 1.2;
process_value_double(&v); //double
struct value v2;
v2.name = "Age";
v2.u.a = 19;
check_if_can_drive(&v2); //int
...
}
void countOranges()
{
struct value v;
v.name = "counter";
v.u.a = ORANGE;
count_objects(&v); //int
}
Ответ 5
Предупреждение: следующее предназначено только для обучения:
Вы можете использовать некоторые уродливые трюки для этого (пока типы данных в вашем союзе имеют разные размеры, что является настоящим случаем):
#include <stdio.h>
typedef union someunion {
int a;
double b;
} myunion;
typedef struct somestruct {
int uniontype;
myunion numbers;
} mystruct;
#define UPDATE_CONTENT(container, value) if ( \
((sizeof(value) == sizeof(double)) \
? (container.uniontype = ((container.numbers.b = value), 2)) \
: (container.uniontype = ((container.numbers.a = value), 1))))
int main()
{
mystruct my_container;
UPDATE_CONTENT(my_container, 42);
printf("%d\n", my_container.uniontype);
UPDATE_CONTENT(my_container, 37.1);
printf("%d\n", my_container.uniontype);
return (0);
}
Но я советую вам никогда этого не делать.
Ответ 6
Может быть, мой вариант помогает
struct Table
{
char mas[10];
int width;
int high;
union stat
{
int st;
char v;
} un;
};
Table tble[2];
strcpy(tble[0].mas, "box");
tble[0].high = 12;
tble[0].width = 14;
tble[0].un.v = 'S';
strcpy(tble[1].mas, "bag");
tble[1].high = 12;
tble[1].width = 14;
tble[1].un.st = 40;
//struct Table *ptbl = &tble[0];
//ptbl++;
for (int i = 0; i < 2; i++)
{
void *pt = &tble[i].un;
if(*((char*)pt) == 'S')
sort(put_on_bag_line);
else
sort(put_on_box_line);
}