2013-05-18 18 views
16

powiedzmy mamy UNION:Jak sprawdzić, jaki typ jest obecnie używany w związku?

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

to możliwe, aby sprawdzić, jakiego typu jest w Unii po ustawić np a = 123? Moje podejście polega na dodaniu tego związku do pewnej struktury i ustawieniu uniontype na 1, gdy jest int i 2, gdy jest podwójne.

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

Czy istnieje lepsze rozwiązanie?

Odpowiedz

13

Czy istnieje lepsze rozwiązanie?

Nie, proponowane rozwiązanie jest najlepsze (i jedyne). union s są dość uproszczone, nie "śledzić" tego, co przypisałeś do czego. Wszystko, co robią, to pozwolić ci ponownie użyć tego samego zakresu pamięci dla wszystkich swoich członków. Nie zapewniają niczego poza tym, więc zamknięcie ich w struct i użycie pola "typ" do śledzenia jest dokładnie tym, co należy zrobić.

+7

FYI, ta technika nazywa się "związkiem oznaczonym tagami". –

+2

Lepszym rozwiązaniem jest użycie wartości wyliczeniowych zamiast 1, 2 itd. –

6

C nie śledzi automatycznie, które pole w związku jest aktualnie w użyciu. (W rzeczywistości uważam, że czytanie z "niewłaściwego" pola powoduje wdrożenie określonych zachowań.) W związku z tym od twojego kodu zależy, który z nich jest aktualnie używany/wypełniany.

Twoje podejście do utrzymania oddzielna zmienna „uniontype” jest bardzo powszechne podejście do tego, a powinno działać dobrze.

3

Nie ma sposobu, aby bezpośrednio zapytać typ aktualnie przechowywane w union.

Jedyne sposoby znać rodzaj przechowywanych w union mają mieć wyraźny flagi (jak w przykładzie mystruct), lub w celu zapewnienia, że ​​kontrola płynie tylko do niektórych części kodu, gdy Unia znany element aktywny .

2

W zależności od zastosowania, jeśli jest to krótkotrwały obiekt może być w stanie zakodować typ na przepływ sterowania, tj. mają oddzielne bloki/funkcje dla obu przypadkach

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

Ostrzeżenie: po to właśnie za cel nauczania:

Można użyć kilka brzydkich sztuczek, aby to zrobić (tak długo, jak typy danych w Unii mają różne rozmiary, co jest w tym przypadku):

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

Ale radzę ci nigdy tego nie robić.

Powiązane problemy