C11 ajoute, entre autres, "Structures et unions anonymes".
J'ai fouillé, mais je n'ai pas pu trouver d'explication claire sur le moment où les structures et les unions anonymes seraient utiles. Je demande parce que je ne comprends pas complètement ce que c'est. Je comprends que ce sont des structures ou des unions sans nom par la suite, mais j'ai toujours (dû?) Traiter cela comme une erreur, donc je ne peux concevoir qu'une utilisation pour les structures nommées.
L'union anonyme à l'intérieur des structures est très utile dans la pratique. Considérez que vous voulez implémenter un type de somme discriminée (ou nion étiquetée ), un agrégat avec un booléen et soit un flottant soit un char*
(c'est-à-dire une chaîne), selon le drapeau booléen. Avec C11, vous devriez pouvoir coder
typedef struct {
bool is_float;
union {
float f;
char* s;
};
} mychoice_t;
double as_float(mychoice_t* ch)
{
if (ch->is_float) return ch->f;
else return atof(ch->s);
}
Avec C99, vous devrez nommer l'union et coder ch->u.f
et ch->u.s
qui est moins lisible et plus verbeux.
Une utilisation typique et réelle des structures et des unions anonymes est de fournir une vue alternative aux données. Par exemple, lors de l'implémentation d'un type de point 3D:
typedef struct {
union{
struct{
double x;
double y;
double z;
};
double raw[3];
};
}vec3d_t;
vec3d_t v;
v.x = 4.0;
v.raw[1] = 3.0; // Equivalent to v.y = 3.0
v.z = 2.0;
Ceci est utile si vous vous connectez au code qui attend un vecteur 3D comme pointeur vers trois doubles. Au lieu de faire f(&v.x)
ce qui est moche, vous pouvez faire f(v.raw)
ce qui rend votre intention claire.
struct bla {
struct { int a; int b; };
int c;
};
le type struct bla
a un membre d'un type de structure anonyme C11.
struct { int a; int b; }
n'a pas de balise et l'objet n'a pas de nom: c'est un type de structure anonyme.
Vous pouvez accéder aux membres de la structure anonyme de cette façon:
struct bla myobject;
myobject.a = 1; // a is a member of the anonymous structure inside struct bla
myobject.b = 2; // same for b
myobject.c = 3; // c is a member of the structure struct bla
Je ne sais pas pourquoi C11 autorise les structures anonymes à l'intérieur des structures. Mais Linux l'utilise avec ne certaine extension de langue :
/**
* struct blk_mq_ctx - State for a software queue facing the submitting CPUs
*/
struct blk_mq_ctx {
struct {
spinlock_t lock;
struct list_head rq_lists[HCTX_MAX_TYPES];
} ____cacheline_aligned_in_smp;
/* ... other fields without explicit alignment annotations ... */
} ____cacheline_aligned_in_smp;
Je ne sais pas si cet exemple est strictement nécessaire, sauf pour clarifier l'intention.
EDIT: J'ai trouvé un autre modèle similaire qui est plus clair. La fonction de structure anonyme est utilisée avec cet attribut:
#if defined(RANDSTRUCT_PLUGIN) && !defined(__CHECKER__)
#define __randomize_layout __attribute__((randomize_layout))
#define __no_randomize_layout __attribute__((no_randomize_layout))
/* This anon struct can add padding, so only enable it under randstruct. */
#define randomized_struct_fields_start struct {
#define randomized_struct_fields_end } __randomize_layout;
#endif
C'est à dire. un plugin d'extension de langage/compilateur pour randomiser l'ordre des champs (exploit de style ASLR "durcissement"):
struct kiocb {
struct file *ki_filp;
/* The 'ki_filp' pointer is shared in a union for aio */
randomized_struct_fields_start
loff_t ki_pos;
void (*ki_complete)(struct kiocb *iocb, long ret, long ret2);
void *private;
int ki_flags;
u16 ki_hint;
u16 ki_ioprio; /* See linux/ioprio.h */
unsigned int ki_cookie; /* for ->iopoll */
randomized_struct_fields_end
};