Comment comstackr du code C avec des structures / unions anonymes?

Je peux le faire en c ++ / g ++:

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

Alors,

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

marchera.

Comment fait-on cela en c avec gcc? j’ai

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

Mais je reçois des erreurs tout autour, en particulier

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

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

-fms-extensions la fonctionnalité que vous (et moi) voulons.

(Cette réponse s’applique à C99, pas à C11).

C99 n’a pas de structures anonymes ni de syndicats. Vous devez les nommer:

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

Et puis vous devez utiliser le nom lorsque vous y accédez:

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

Dans ce cas, comme votre structure de niveau supérieur possède un seul élément de type union, vous pouvez simplifier ceci:

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

et accéder aux données devient maintenant:

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

La nouvelle norme C11 soutiendra les structures et les syndicats anonymes, voir l’avant-paragraphe 6 du projet d’avril 2011.

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

La partie étrange est que gcc et clang supportent désormais des structures anonymes et des unions en mode C89 et C99. Dans ma machine, aucun avertissement ne s’affiche.

On peut aussi toujours faire ce qui suit:

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

Le tableau de longueur nulle n’alloue aucun stockage, et dit simplement à C de “pointer sur la prochaine chose déclarée”. Ensuite, vous pouvez y accéder comme n’importe quel autre tableau:

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

Résultat:

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

Si vous voulez être plus paranoïaque, vous pouvez spécifier manuellement la stratégie d’emballage des données en fonction de votre plate-forme.

Les unions anonymes sont une fonctionnalité du langage C ++. Le langage C n’a pas de syndicats anonymes.

Les structures anonymes n’existent ni dans C ni dans C ++.

La déclaration que vous avez présentée dans votre question pourrait être compilée avec GCC C ++ complier, mais ce ne serait qu’une extension spécifique au compilateur, qui n’a rien à voir avec la norme C ni avec la norme C ++.

De plus, quel que soit le mode d’implémentation, ni le langage C ni le langage C ++ ne garantissent que vos assertions seront maintenues.

Je peux le faire dans GCC sans avertissement

 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. Ce logiciel est gratuit. voir la source pour les conditions de copie. Il n’y a pas de garantie; pas même pour la QUALITÉ MARCHANDE ou la CONFORMITÉ À UN USAGE PARTICULIER.

Les unions d’Anonymouse ne sont ni soutenues dans C.

Notez également que si vous le déclarez de cette façon:

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

Faire

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

Est un comportement indéfini. Vous ne pouvez accéder qu’au dernier membre du syndicat affecté. Dans votre cas, l’utilisation d’une union est fausse et une mauvaise pratique de codage, car elle dépend de nombreuses choses qui ne sont pas spécifiées dans la norme (remplissage …).

En C, vous préférerez quelque chose comme ceci:

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

Et si vous ne voulez pas utiliser v [x], vous pouvez envisager:

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

Le dialecte GNU de C supporte les structures / unions anonymes, mais par défaut, GCC comstack en utilisant une sorte de norme C. Pour utiliser le dialecte GNU, mettez “-std = gnu99” sur la ligne de commande.

Les membres non identifiés de la structure n’étant pas conformes à la norme ANSI / ISO C99 expliquent cela, mais je trouve que quelque chose de drôle se produit, sur certains ports des versions GNU C Comstackr 2.xx, x n’est pas un membre de l’union \ struct y, ce qui est x? “, d’autres fois, c’est l’ol” x est indéfini “,” x n’est pas un membre de struct “, l’enfer je jure avoir vu un” pointeur vers l’inconnu “de temps en temps, à cause de cela.

Donc, professionnellement, j’irais avec tout le monde là-dessus et simplement donner un identifiant au membre struct \ union ou, dans le cas des UNION, réorganiser soigneusement le code pour que l’union identifie un membre d’une structure identifiée et les membres ont été intégrés dans la structure non identifiée du syndicat d’origine, deviennent membres de la structure identifiée et sont utilisés avec soin avec le membre identifié du syndicat. Mais dans les cas où cette dernière méthode ne serait pas un substitut viable, je donnerais simplement un identifiant à la structure désagréable et passerais à autre chose.

Je peux suggérer une solution de contournement intéressante afin d’éviter trop de champs dans la structure. Il est conseillé de prévenir sur les définitions simplement nommées, car cela pourrait créer des conflits.

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

Vous pouvez accéder à la structure comme ceci:

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

Pour finir, ce serait une union de type multi compatible avec 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. */