Come compilare il codice C con strutture / unioni anonime?

Posso farlo in c ++ / g ++:

struct vec3 { union { struct { float x, y, z; }; float xyz[3]; }; }; 

Poi,

 vec3 v; assert(&v.xyz[0] == &v.x); assert(&v.xyz[1] == &v.y); assert(&v.xyz[2] == &v.z); 

funzionerà.

Come si fa a farlo in c con gcc? io ho

 typedef struct { union { struct { float x, y, z; }; float xyz[3]; }; } Vector3; 

Ma ottengo errori in tutto, in particolare

 line 5: warning: declaration does not declare anything line 7: warning: declaration does not declare anything 

secondo http://gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html#Unnamed-Fields

-fms-extensions abiliterà la funzione che tu (e io) vogliamo.

(Questa risposta vale per C99, non C11).

C99 non ha strutture anonime o sindacati. Devi chiamarli:

 typedef struct { union { struct { float x, y, z; } individual; float xyz[3]; } data; } Vector3; 

E poi devi usare il nome per accedervi:

 assert(&v.data.xyz[0] == &v.data.individual.x); 

In questo caso, poiché la struttura di livello superiore ha un singolo elemento di tipo union, puoi semplificare questo:

 typedef union { struct { float x, y, z; } individual; float xyz[3]; } Vector3; 

e l’accesso ai dati ora diventa:

 assert(&v.xyz[0] == &v.individual.x); 

Il nuovo standard C11 supporterà strutture anonime e sindacati, vedere la prefazione al paragrafo 6 del progetto di aprile 2011.

http://en.wikipedia.org/wiki/C1X

La parte strana è che sia gcc che clang ora supportano strutture e unioni anonime in modalità C89 e C99. Nella mia macchina non compaiono avvisi.

Si può anche sempre fare quanto segue:

 typedef struct { float xyz[0]; float x, y, z; }Vec3; 

L’array a lunghezza zero non alloca nessuno spazio di archiviazione e dice semplicemente a C di “puntare a qualsiasi altra cosa dichiarata”. Quindi, puoi accedervi come qualsiasi altro array:

 int main(int argc, char** argv) { Vec3 tVec; for(int i = 0; i < 3; ++i) { tVec.xyz[i] = (float)i; } printf("vec.x == %f\n", tVec.x); printf("vec.y == %f\n", tVec.y); printf("vec.z == %f\n", tVec.z); return 0; } 

Risultato:

 vec.x == 0.000000 vec.y == 1.000000 vec.z == 2.000000 

Se vuoi essere un paranoico in più, puoi specificare manualmente la strategia di impacchettamento dei dati per adattarla alla tua piattaforma.

Le unioni anonime sono una caratteristica del linguaggio C ++. Il linguaggio C non ha unioni anonime.

Le strutture anonime non esistono né in C né in C ++.

La dichiarazione che hai presentato nella tua domanda potrebbe essere compilata con il compilatore GCC C ++, ma sarebbe solo un’estensione specifica del compilatore, che non ha nulla a che fare con C standard o C ++ standard.

Oltre a ciò, indipendentemente da come lo si implementa, né il linguaggio C né il linguaggio C ++ garantiscono che le tue affermazioni rimarranno valide.

Posso farlo in GCC senza preavviso

 typedef union { struct { // human-friendly access float x; float y; float z; float w; }; float xyz[3]; struct { // human-friendly access float r; float g; float b; float a; }; float rgb[3]; } Vector4f; int main() { Vector4f position, normal, color; // human-friendly access position.x = 12.3f; position.y = 2.f; position.z = 3.f; position.w = 1.f; normal.x = .8f; normal.y = .9f; normal.z = .1f; normal.w = 1.f; color.r = 1.f; color.g = .233f; color.b = 2.11f; color.a = 1.1f; // computer friendly access //some_processor_specific_operation(position.vec,normal.vec); return 0; } 

C: \> gcc vec.c -Wall

C: \> gcc –version gcc (GCC) 4.4.0 Copyright (C) 2009 Free Software Foundation, Inc. Questo è un software gratuito; vedere la fonte per le condizioni di copia. Non c’è garanzia; nemmeno per COMMERCIABILITÀ o IDONEITÀ PER UN PARTICOLARE SCOPO.

Le unioni di anonymouse non sono supportate in C.

Nota inoltre che se lo dichiari in questo modo:

 typedef struct { union { struct { float x, y, z; } individual; float xyz[3]; } data; } Vector3; 

fare

 Vector3 v; v.data.xyz[0] = 5; float foo = v.data.individual.x; 

È un comportamento indefinito. È ansible accedere solo all’ultimo membro del sindacato assegnato. Nel tuo caso, l’utilizzo di un’unione è sbagliato e la ctriggers pratica di codifica in quanto dipende da molte cose che non sono specificate nello standard (padding …).

In C preferirai qualcosa del genere:

 typedef struct { float v[3]; } Vec3; 

E se non vuoi usare v [x] potresti prendere in considerazione:

 #define X(V) ((V).v[0]) Vec3 v; X(v) = 5.3; printf("%f\n", X(v)); 

Il dialetto GNU di C supporta strutture / unioni anonime, ma per impostazione predefinita GCC compila usando un qualche tipo di standard C. Per usare il dialetto GNU, metti “-std = gnu99” sulla riga di comando.

I membri della struct non identificati che non sono standard ANSI / ISO C99 lo spiegano, ma trovo che una cosa divertente succeda, su alcune porte delle versioni GNU C Compiler 2.xx, usando i membri di struct non identificati funziona, li trova, non dice cose come ” x non è un membro di union \ struct y, che cos’è x? “, altre volte, è il vecchio” x è indefinito “,” x non è un membro di struct “, diavolo giuro che ho visto un” puntatore a sconosciuto ” “una volta tanto, a causa di questo.

Quindi io, professionalmente, andrei con tutti gli altri su questo e solo ether daremo al membro struct \ union un identificatore, o nel caso di UNION, riordinare attentamente il codice in modo che l’unione finisca con un membro identificato di una struttura identificata e i membri che sono stati incorporati nella struttura non identificata dell’unione originale, diventano membri della struttura identificata e sono attentamente utilizzati con il membro del sindacato identificato. Ma in quei casi il secondo metodo non sarebbe stato un sostituto funzionale, avrei solo dato alla struttura un identificatore fastidioso e andare avanti.

Posso suggerire una soluzione interessante per evitare troppi campi all’interno della struttura. Si consiglia di avvertire su semplicemente named definisce, in quanto potrebbe creare conflitti.

 #define x ___fl_fld[0] #define y ___fl_fld[1] #define z ___fl_fld[2] #define w ___fl_fld[3] #define r ___fl_fld[0] #define g ___fl_fld[1] #define b ___fl_fld[2] #define a ___fl_fld[3] typedef union { float ___fl_fld[4]; float xyz[3]; float rgb[3]; } Vector3; 

Potresti accedere alla struttura in questo modo:

 Vector3 v; assert(&v.x == &v.r); //Should return true 

Per finire, questo sarebbe un sindacato di tipo multi compatibile con C99:

 #define u8llsb __u8[0] #define u8lmsb __u8[1] #define u8mlsb __u8[2] #define u8mmsb __u8[3] #define u16lsb __u16[0] #define u16msb __u16[1] #define u16 __u16[0] #define u8lsb __u8[0] #define u8msb __u8[1] typedef union { uint32_t u32; int32_t i32; uint16_t __u16[2]; uint8_t __u8[4]; } multitype_t; multitype_t Var; var.u32; var.i32; var.u8llsb; /* etc. */