2012-11-29 7 views
8

Sto lavorando sul progetto open source cosiddetto Hotspot, e guardando l'attuazione ho trovato un sindacato nidificato brutto in struct cercando così:Come usare c unione nidificato in struct senza nome

typedef struct RC_model_t_st 
{ 
    union 
    { 
     struct block_model_t_st *block; 
     struct grid_model_t_st *grid; 
    }; 
    /* block model or grid model */ 
    int type; 
    thermal_config_t *config; 
}RC_model_t; 

Per quanto ne so in C/C++ quell'unione è inaccessibile. Quindi, come qualcuno può fare uso dell'unione dichiarata in tal modo e per quale scopo?

Grazie!

+0

Correlato: http://stackoverflow.com/questions/1972003/how-to-use-anonymous-structions-unions-in-c – zch

risposta

-4

prima di tutto voglio dire che Un connubio, è un insieme di variabili di tipo diverso, proprio come una struttura. Tuttavia, con i sindacati, puoi archiviare le informazioni in un solo campo in qualsiasi momento.

I sindacati sono fondamentalmente utilizzati per il risparmio di memoria & la sua dimensione è uguale al più grande membro del sindacato.

E per accedere ai campi dati di un'unione, utilizzare l'operatore punto (.) Proprio come si farebbe per una struttura e spiegato da @Atmocreations. Quando un valore viene assegnato a un membro, gli altri membri vengono sballottati poiché condividono la stessa memoria.

come un esempio in cui i raccordi possono essere utili è

union time  
     { 
     long time_in_sec; 
     double time_in_mili_sec; 
     }mytime; 

.... L'unione di cui sopra potrebbe essere utilizzato sia per memorizzare l'ora corrente (in secondi) per tenere il tempo esatto di una seconda . Oppure potrebbe essere usato per contenere il tempo in modo preciso per un millisecondo. Presumibilmente ci sono momenti in cui vorresti uno o l'altro, ma non entrambi. Questa dichiarazione dovrebbe sembrare familiare. È uguale a una definizione di struct, ma con la parola chiave union invece di struct.

per ulteriori informazioni http://msdn.microsoft.com/en-us/library/5dxy4b7b(v=vs.80).aspx

+0

Questa è la risposta più completa per me. Grazie! – zwx

+0

@zwx che è y stackoverflow è qui .. – akp

+0

@akp: prestare attenzione. L'allineamento potrebbe rompersi a seconda dell'architettura – Atmocreations

8

senza essere sicuro e senza aver provato:

l'Unione stessa non è accessibile, ma è soci sono.

Pertanto si dovrebbe essere in grado di fare riferimento a obj.block e obj.grid

+1

Vuoi dire che obj è RC_model_t? – zwx

18

Si tratta di un'unione anonima . In C++, come per [class.union], paragrafo 5:

Ai fini della ricerca del nome, dopo la definizione unione anonima, i membri del sindacato anonima sono considerati sono stati definiti nel ambito in cui viene dichiarata l'unione anonima

Ciò significa che è possibile accedere ai suoi membri come se fossero membri di RC_model_t_st.

+0

Ok. Quindi se riesco ad accedervi come membri della struttura, non capisco perché qualcuno li inserirà nell'unione anonima? – zwx

+1

@zwx Perché è ancora un sindacato - occupano lo stesso spazio di archiviazione. – Angew

+0

Con ogni variabile, allocate dello spazio di memoria di n byte. Ora il tipo di variabili definisce solo, quanto spazio e come deve essere interpretato il contenuto di questo spazio. Con un'unione, la variabile utilizza lo spazio del tipo più grande, l'interpretazione dipende dal membro a cui accedi – Atmocreations

2

I nomi dichiarati in un'unione anonima vengono utilizzati direttamente, come le variabili non membro. Una buona ragione per farlo è di risparmiare memoria.

#include <iostream> 

int main(int argc, char **argv) { 
    union { 
     double first; 
     double second; 
    }; 

    first = 10.001; 
    second = 3.141592; 
    std::cout << first << " " << second << std::endl; 

    first = 10.002; 
    std::cout << first << " " << second << std::endl; 
} 
3

Questo codice qui (https://gist.github.com/klange/4042963) mostra come accedere alle unioni anonime all'interno struct.Devi solo accedere ai membri dell'unione annidata come se fossero membri della struttura.

typedef struct { 
    union { 
     char * company; 
     char * school; 
     char * project; 
    }; 
    union { 
     char * location; 
     char * url; 
    }; 
    union { 
     char * title; 
     char * program; 
    }; 

    time_t started; 
    time_t left; 

    char * description[]; 
} thing_t; 

typedef thing_t job_t; 

job_t yelp = { 
    .company = "Yelp, Inc.", 
    .location = "San Francisco, CA", 
    .title = "Software Engineer, i18n", 
    .started = 1339977600, 
    .left  = CURRENT, 
    .description = { 
     "Developed several internal tools and libraries", 
     "Provided critical input and design work for Yelp's launch in Japan", 
     NULL 
    } 
}; 
2

di approfondire la risposta fornita dal Angew citando lo standard per quanto riguarda le unioni anonime e le strutture, ho pensato di fornire un campione di codice sorgente C con l'output generato da quel campione che mostra come i valori sono allocati all'interno di un struct e a union composto da componenti struct e union.

Lo standard citato da Angew è:

Ai fini della ricerca del nome, dopo la definizione unione anonima, i membri del sindacato anonimo sono considerati sono stati definiti nel campo di applicazione in cui la viene dichiarata l'unione anonima.

Il codice sorgente di un struct composto da strutture e unioni denominate e anonime è simile al seguente. Si sta utilizzando Visual Studio 2005 e lo #pragma (pack, 1) viene utilizzato per allineare tutto su un limite char in modo che non ci siano buchi di memoria. C'è anche una semplice macro C Preprocessore definita per rendere l'output più leggibile e più facile da codificare.

typedef unsigned char UCHAR; 

// use of Microsoft Visual Studio pragma to force char alignment for the struct. 
#pragma pack(push, 1) 
const struct { 
    union { 
     const UCHAR myArray[]; // this array shares memory with struct following 
     struct { 
      const UCHAR iOne; 
      const UCHAR iTwo; 
      const UCHAR iThree; 
     }; // anonymous struct accessed by specifying Things. 
    };  // anonymous union accessed by specifying Things. 
// const UCHAR myArray[]; // will cause error - "error C2020: 'myArray' : 'struct' member redefinition" 
    union { 
     const UCHAR myArray[]; // this array shares memory with struct following 
     struct { 
      const UCHAR iOne; 
      const UCHAR iTwo; 
      const UCHAR iThree; 
     } s; // named struct accessed by specifying Things.u.s 
    } u;  // named union accessed by specifying Things.u 
} Things = {1, 2, 4, 8, 9, 10, 22, 23, 24, 25}; 
#pragma pack(pop) 

// a little helper macro to make the output easier to code. 
#define PRINTF_VAL(x) printf ("%s %d \n", #x, x) 

int itSelf (UCHAR iMask) 
{ 
    int iMatch = -1; 

    int jj = 0; 
    jj = Things.myArray[0]; PRINTF_VAL(Things.myArray[0]); 
    jj = Things.myArray[1]; PRINTF_VAL(Things.myArray[1]); 
    jj = Things.myArray[2]; PRINTF_VAL(Things.myArray[2]); 
    jj = Things.myArray[3]; PRINTF_VAL(Things.myArray[3]); 
    jj = Things.myArray[4]; PRINTF_VAL(Things.myArray[4]); 
    jj = Things.iOne; PRINTF_VAL(Things.iOne); 
    jj = Things.iTwo; PRINTF_VAL(Things.iTwo); 
    jj = Things.iThree; PRINTF_VAL(Things.iThree); 

    jj = Things.u.myArray[0]; PRINTF_VAL(Things.u.myArray[0]); 
    jj = Things.u.myArray[1]; PRINTF_VAL(Things.u.myArray[1]); 
    jj = Things.u.myArray[2]; PRINTF_VAL(Things.u.myArray[2]); 
    jj = Things.u.myArray[3]; PRINTF_VAL(Things.u.myArray[3]); 
    jj = Things.u.myArray[4]; PRINTF_VAL(Things.u.myArray[4]); 
    jj = Things.u.s.iOne; PRINTF_VAL(Things.u.s.iOne); 
    jj = Things.u.s.iTwo; PRINTF_VAL(Things.u.s.iTwo); 
    jj = Things.u.s.iThree; PRINTF_VAL(Things.u.s.iThree); 

    return iMatch + 1; 
} 

L'output generato da questa funzione assomiglia:

Things.myArray[0] 1 
Things.myArray[1] 2 
Things.myArray[2] 4 
Things.myArray[3] 8 
Things.myArray[4] 9 
Things.iOne 1 
Things.iTwo 2 
Things.iThree 4 
Things.u.myArray[0] 8 
Things.u.myArray[1] 9 
Things.u.myArray[2] 10 
Things.u.myArray[3] 22 
Things.u.myArray[4] 23 
Things.u.s.iOne 8 
Things.u.s.iTwo 9 
Things.u.s.iThree 10 

L'output mostra la sovrapposizione tra i vari componenti del principale struct, Things causati dall'uso di unioni. È anche possibile vedere come vengono referenziati i componenti dell'anonimo struct e union rispetto a quelli dei componenti denominati struct e union.

Anche solo per divertimento ho provato ad aggiungere una definizione di array di const UCHAR myArray[]; dopo l'anonimo union contenente const UCHAR myArray[]; per vedere cosa sarebbe successo. Il compilatore si è lamentato di un errore di error C2020: 'myArray' : 'struct' member redefinition. L'aggiunta è commentata nella definizione struct di Things precedente. Tuttavia, dal momento che il secondo utilizzo di const UCHAR myArray[]; è in un valore denominato union, la compilazione funziona perché è possibile accedere al secondo utilizzo specificando il nome dell'unione.