2011-01-07 9 views

Odpowiedz

12

Bezimienny union wewnątrz struct sens, ponieważ pozwala zapoznać się z członkami unii bez podania jego nazwy, a więc krótszy kod:

struct { 
    int a; 

    union { 
    int b, c, d; 
    }; 
} foo; 

Więc dostępie do członków union jest jak dostęp do członka struktury zawierającej: foo.a i foo.b. W przeciwnym razie musisz użyć foo.union_name.b, aby uzyskać dostęp do członka związku.

Oczywiście programista "użytkowy" korzystający z takiej struktury powinien mieć świadomość, że ustawienie foo.c wpływa na wartość foo.b i foo.d.

Z tego samego powodu odwrotnego można zrobić, a mianowicie wprowadzenie anonimowego struct wewnątrz union:

union { 
    struct { 
    int a, b; 
    }; 

    int c; 
} foo; 

ten sposób foo.a i foo.b mogą być używane jednocześnie i foo.c mogą być wykorzystane w innym przypadku.

Nie mogę wymyślić żadnych innych zastosowań anonimowych struktur lub związków. "Deklarowanie" anonimowego struct/union jest oksymoronem i jest tak jak powiedzenie int; zamiast int a;.

+0

To naprawdę miłe, nie wiedziałem o tym.Uratowałeś mi wiele klawiszy! – GWW

+1

To dotyczy bezimiennych związków, a co z bezimiennymi strukturami, jak w przykładzie dostarczonym przez OP? –

0

W tym przypadku twoje odwzorowanie struktury (zawierającej 4 bajty) i niepodpisane int (4 bajty również) do tej samej lokalizacji pamięci.

+0

Myślę, że brakowało ci punktu: OP wie, do czego służą związki, po prostu pyta o bezimienne struktury w związkach. – ereOn

+0

Przejście przez tytuł "Do czego można użyć bezimiennej struktury lub związku?" Nie sądzę, żebym przeoczył cały punkt. Ale tak, ostatnia część pytania odnosi się do struktury, kiedy ponownie ją przeczytam. –

1

Możesz użyć anonimowej struktury w strukturze lub klasie, aby zgrupować pewną wartość, która jest zwykłym starym danymi, aby ułatwić inicjalizację instancji (z memset), ale nie może tego zrobić, ponieważ klasa pochodzi z innej.

Exemple:

#include <string.h> 
class Base 
{ 
private: 
    int field1; 
    int field2; 

public: 
    Base() 
    { 
     // initialize field1, field2 
    } 

    virtual void DoSomething(); 
}; 

class Derived : public Base 
{ 
private: 
    struct 
    { 
     int field2; 
     int field3; 
     int field4; 
     // ... 
     int field99; 
    } data; 

public: 
    Derived() 
    : Base() 
    { 
     memset(&data, 0, sizeof(data)); 

     // if you didn't group those value in an anonymous struct 
     // you would have to do something like that (not safe): 
     // memset(sizeof(Base) + (char*)this, 0, sizeof(Derived) - sizeof(Base)); 
    } 
}; 

Należy pamiętać, że istnieje lepsze alternatywy (w moim przykładzie za pomocą std :: vector lub int [99]). Ale czasami może się przydać.

+0

+1. to dobry przykład, gdy odpowiednia odpowiedź nie miała żadnego głosu, a post, który nie odpowiedział na pytanie, miał 6 głosów. –

5

Dzieje się tak głównie dlatego, że struct i union są tak podobne. Ogólnie rzecz biorąc, przydatne jest posiadanie anonimowych struktur w związkach i anonimowych związków w strukturach, ale zagnieżdżanie struktur w strukturach lub związkach w związkach jest w większości równoznaczne z bezpośrednim wymienianiem ich członków.

Należy pamiętać, że do przeliczania wartości nie należy stosować związków, ponieważ nie ma absolutnie żadnych gwarancji układu.

+0

+1 tylko dla ostrzeżenia! Układ danych leży całkowicie w gestii kompilatora, więc nie tylko jest nieprzenośny, ale może również zmieniać się w zależności od opcji kompilatora itp. –

+0

Czy "#pragma pack" nie ma takich gwarancji i możliwości przenoszenia? –

+1

#pragma z definicji nie jest przenośna. –

Powiązane problemy