2013-05-18 5 views
16

wir sagen, dass wir eine Gewerkschaft haben:Wie überprüft man, welcher Typ derzeit in der Union verwendet wird?

typedef union someunion { 
    int a; 
    double b; 
} myunion; 

Ist es möglich, zu prüfen, welche Art in der Vereinigung ist, nachdem ich zum Beispiel festgelegt a = 123? Meine Vorgehensweise besteht darin, diese Union zu einer Struktur hinzuzufügen und uniontype auf 1 zu setzen, wenn es int ist, und 2, wenn es doppelt ist.

typedef struct somestruct { 
    int uniontype 
    myunion numbers; 
} mystruct; 

Gibt es eine bessere Lösung?

Antwort

13

Gibt es eine bessere Lösung?

Nein, die Lösung, die Sie zeigen, ist die beste (und die einzige). s sind ziemlich simpel, nicht "verfolgen", was Sie zu was zugewiesen haben. Sie können nur denselben Speicherbereich für alle ihre Mitglieder verwenden. Sie bieten nichts anderes als das, so dass sie in eine struct eingeschlossen werden und ein "Typ" -Feld für die Verfolgung verwendet wird, ist genau das richtige, was zu tun ist.

+7

FYI, diese Technik wird eine "markierte Union" genannt. –

+2

Eine bessere Lösung ist die Verwendung von Enum-Werten anstelle von 1, 2 usw. –

6

C verfolgt nicht automatisch, welches Feld in einer Union gerade verwendet wird. (In der Tat, ich glaube, Lesen aus dem "falschen" Feld führt zu Implementierung definiert Verhalten.) Daher ist es an Ihrem Code zu verfolgen, welche derzeit verwendet/ausgefüllt ist.

Ihr Ansatz, eine separate Variable vom Typ "union" beizubehalten, ist ein sehr gebräuchlicher Ansatz und sollte gut funktionieren.

3

Es ist nicht möglich, den aktuell in einer union gespeicherten Typ direkt abzufragen. Die einzigen Möglichkeiten, den in einem union gespeicherten Typ zu kennen, sind ein explizites Flag (wie in Ihrem mystruct Beispiel) oder sicherzustellen, dass die Kontrolle nur zu bestimmten Teilen des Codes fließt, wenn die Union ein bekanntes aktives Element hat .

2

Je nach Anwendung, wenn es sich um ein kurzlebiges Objekt handelt, können Sie möglicherweise den Typ im Kontrollfluss codieren, dh. separate Blöcke/Funktionen für beide Fälle

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 
    } 
2

Achtung: Die folgende ist nur für einen bestimmten Zweck zu lernen:

Sie einige hässliche Tricks so zu tun, verwenden könnte (solange die Datentypen in Ihrer Gewerkschaft haben verschiedene Größen, die der vorliegende Fall ist):

#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); 
} 

Aber ich rate dir, dies nie zu tun.

Verwandte Themen