Comment vérifier quel type est actuellement utilisé dans union?
Disons que nous avons une union:
typedef union someunion {
int a;
double b;
} myunion;
Est-il possible de vérifier quel type est dans union après avoir défini par exemple A = 123? Mon approche est d'ajouter cette union à une structure et de définir uniontype à 1 quand c'est int et 2 Quand c'est double.
typedef struct somestruct {
int uniontype
myunion numbers;
} mystruct;
Y a-t-il une meilleure solution?
5 réponses
Y a-t-il une meilleure solution?
Non, la solution que vous montrez est la meilleure (et la seule). union
s sont assez simplistes, ne pas "suivre" ce que vous avez assigné à quoi. Tout ce qu'ils font est de vous permettre de réutiliser la même plage de mémoire pour tous leurs membres. Ils ne fournissent rien d'autre au-delà de cela, donc les enfermer dans un struct
et utiliser un champ "type" pour le suivi est précisément la bonne chose à faire.
C ne permet pas automatiquement de savoir quel champ d'une union est actuellement utilisé. (En fait, je crois que la lecture du" mauvais " champ entraîne un comportement défini par l'implémentation.) En tant que tel, il appartient à votre code de garder une trace de celui qui est actuellement utilisé / rempli.
Votre approche pour conserver une variable 'uniontype' distincte est une approche très courante et devrait bien fonctionner.
Il n'y a aucun moyen d'interroger directement le type actuellement stockés dans un union
.
Les seules façons de connaître le type stocké dans un union
sont d'avoir un indicateur explicite (comme dans votre exemple mystruct
), ou de s'assurer que le contrôle ne circule que vers certaines parties du code lorsque l'union a un élément actif connu.
Selon l'application, s'il s'agit d'un objet de courte durée, vous pourrez peut-être encoder le type dans le flux de contrôle, c'est-à-dire. avoir des blocs/fonctions distincts pour les deux cas
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
}
attention: ce qui suit est juste à des fins d'apprentissage:
Vous pouvez utiliser quelques astuces laides pour le faire (tant que les types de données dans votre union ont des tailles différentes, ce qui est le cas présent):
#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);
}
Mais je vous conseille de ne jamais faire cela.