Je peux le faire en c ++/g ++:
struct vec3 {
union {
struct {
float x, y, z;
};
float xyz[3];
};
};
Ensuite,
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
activera la fonctionnalité que vous (et moi) voulons.
(Cette réponse s'applique à C99, pas à C11).
C99 n'a pas de structures ou de syndicats anonymes. 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, parce que votre structure de niveau supérieur a 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 anonymes et les syndicats, voir le paragraphe 6 de l'avant-projet du projet d'avril 2011.
http://en.wikipedia.org/wiki/C1X
La partie étrange est que gcc et clang prennent désormais en charge les structures anonymes et les unions en mode C89 et C99. Dans ma machine, aucun avertissement n'apparaît.
On peut également 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 indique simplement à C de "pointer vers 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 paranoïaque supplémentaire, vous pouvez spécifier manuellement la stratégie de compression des données en fonction de votre plate-forme.
Les unions anonymes sont une fonctionnalité du langage C++. Le langage C n'a pas d'unions anonymes.
Les structures anonymes n'existent ni en C ni en C++.
La déclaration que vous avez présentée dans votre question peut être compilée avec GCC C++ complier, mais ce ne serait qu'une extension spécifique au compilateur, qui n'a rien à voir avec ni le C standard ni le C++ standard.
De plus, quelle que soit la façon dont vous l'implémentez, ni le langage C ni le langage C++ ne garantissent que vos assertions tiendront.
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. Il s'agit d'un logiciel libre; voir la source pour les conditions de copie. Il n'y a AUCUNE garantie; pas même pour la QUALITÉ MARCHANDE ou l'aptitude à un usage particulier.
Les syndicats Anonymouse ne sont pas soutenus en 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 une mauvaise et mauvaise pratique de codage car elle dépend de beaucoup de choses qui ne sont pas spécifiées dans la norme (padding ...).
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 pourriez envisager:
#define X(V) ((V).v[0])
Vec3 v;
X(v) = 5.3;
printf("%f\n", X(v));
Les membres de structure non identifiés qui ne sont pas la norme ANSI/ISO C99 l'expliquent, mais je trouve une drôle de chose qui se produit, sur certains ports des versions GNU C Compiler 2.xx, en utilisant des membres de structure non identifiés, cela trouve eux, ne dit pas des trucs comme "x n'est pas membre de l'union\struct y, qu'est-ce que x?", d'autres fois, c'est l'ol '"x n'est pas défini", "x n'est pas membre de struct", 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 à ce sujet et je donnerais simplement un identifiant au membre struct\union, ou dans le cas des UNIONS, réorganiser soigneusement le code afin que le syndicat devienne un membre identifié d'une structure identifiée et les membres qui ont été intégrés dans la structure non identifiée du syndicat d'origine, sont devenus membres de la structure identifiée et sont soigneusement utilisés avec le membre du syndicat identifié. Mais dans ces cas, si cette dernière méthode ne serait pas un substitut réalisable, je donnerais simplement un identifiant à la structure ennuyeuse et passer à autre chose.
Le dialecte GNU de C prend en charge les structures/unions anonymes, mais par défaut GCC compile en utilisant une sorte de C. standard. Pour utiliser le dialecte GNU, mettez "- std = gnu99 "sur la ligne de commande.