Union anonyme dans struct pas en c99?

Voici le code de problème très simplifié que j’ai:

 enum node_type {
     t_int, t_double
 };

 struct int_node {
     int valeur;
 };

 struct double_node {
     valeur double;
 };

 struct node {
     enum type_noeud;
     syndicat { 
          struct int_node int_n; 
          struct double_node double_n; 
      };
 };

 int main (void) {
     struct int_node i;
     valeur i = 10;
     noeud de structure n;
     n.type = t_int;
     n.  int_n = i;
     retourne 0;
 }

Et ce que je ne comprends pas, c’est ceci:

 $ cc us.c 
 $ cc -std = c99 us.c 
 us.c: 18: 4: avertissement: la déclaration ne déclare rien
 us.c: Dans la fonction 'main':
 us.c: 26: 4: erreur: 'struct node' n'a pas de membre nommé 'int_n'

Utiliser GCC sans l’option -std comstack le code ci-dessus sans aucun problème (et le code similaire fonctionne plutôt bien), mais il semble que c99 n’autorise pas cette technique. Pourquoi est-ce le cas et est-il possible de faire en sorte que c99 (ou c89 , c90 ) soit compatible? Merci.

Les unions anonymes sont une extension GNU, ne faisant partie d’aucune version standard du langage C. Vous pouvez utiliser -std = gnu99 ou quelque chose du genre pour les extensions c99 + GNU, mais il est préférable d’écrire correctement le C et de ne pas compter sur des extensions qui ne fournissent rien d’autre que du sucre syntaxique …

Edit: Les unions anonymes ont été ajoutées en C11, elles font désormais partie intégrante du langage. On peut supposer que -std=c11 vous permet de les utiliser.

Je trouve cette question environ un an et demi après tout le monde, donc je peux donner une réponse différente: les structures anonymes ne sont pas dans la norme C99, mais elles sont dans la norme C11. GCC et clang supportent déjà cela (le standard C11 semble avoir levé la fonctionnalité de Microsoft, et GCC a fourni un support pour certaines extensions MSFT depuis un certain temps).

Eh bien, la solution consistait à nommer l’instance de l’union (qui peut restr anonyme en tant que type de données), puis à utiliser ce nom comme proxy.

 $ diff -u old_us.c us.c 
 --- old_us.c 2010-07-12 13: 49: 25.000000000 +0200
 +++ us.c 2010-07-12 13: 49: 02.000000000 +0200
 @@ -15,7 +15,7 @@
    syndicat {
      struct int_node int_n;
      struct double_node double_n;
 -};
 +} données;
  };

  int main (void) {
 @@ -23,6 +23,6 @@
    valeur i = 10;
    noeud de structure n;
    n.type = t_int;
 - n.int_n = i;
 + n.data.int_n = i;
    retourne 0;
  }

Maintenant, il comstack en c99 sans aucun problème.

 $ cc -std = c99 us.c 
 $ 

Note: Je ne suis pas content de cette solution de toute façon.

L’union doit avoir un nom et être déclarée comme ceci:

 union UPair { struct int_node int_n; struct double_node double_n; }; UPair X; X.int_n.value = 12; 

Une autre solution consiste à placer la valeur d’en-tête commune ( enum node_type type ) dans chaque structure et à transformer votre structure de niveau supérieur en union. Ce n’est pas exactement “Don’t Repeat Yourself”, mais cela évite à la fois les syndicats anonymes et les valeurs de procuration inconfortables.

 enum node_type { t_int, t_double }; struct int_node { enum node_type type; int value; }; struct double_node { enum node_type type; double value; }; union node { enum node_type type; struct int_node int_n; struct double_node double_n; }; int main(void) { union node n; n.type = t_int; // or n.int_n.type = t_int; n.int_n.value = 10; return 0; } 

En regardant 6.2.7.1 de C99, je vois que l’identifiant est facultatif:

 struct-or-union-specifier: struct-or-union identifier-opt { struct-declaration-list } struct-or-union identifier struct-or-union: struct union struct-declaration-list: struct-declaration struct-declaration-list struct-declaration struct-declaration: specifier-qualifier-list struct-declarator-list ; specifier-qualifier-list: type-specifier specifier-qualifier-list-opt type-qualifier specifier-qualifier-list-opt 

J’ai fait des recherches de haut en bas et je ne trouve aucune référence à des syndicats anonymes contre les spécifications. Le suffixe -opt entier indique que la chose, dans ce cas l’ identifier est facultative selon 6.1.