Les «structures anonymes» sont-elles standard? Et, vraiment, qu’est-ce qu’ils * sont *?

MSDN estime que les structures anonymes ne sont pas standard en C ++:

Une extension Microsoft C vous permet de déclarer une variable de structure dans une autre structure sans lui donner de nom. Ces structures nestedes sont appelées structures anonymes. C ++ n’autorise pas les structures anonymes.

Vous pouvez accéder aux membres d’une structure anonyme comme s’ils étaient membres de la structure contenant.

@ K-ballo est d’accord .

On m’a dit que cette fonctionnalité n’est pas nécessairement la même chose que la création d’une structure non nommée, mais je ne vois pas de distinction en termes de libellé standard.

C ++ 11 dit:

[C++11: 9/1] : [..] Spécificateur de classe dont le chef de classe omet le nom-classe-tête définit une classe sans nom.

et fournit une construction grammaticale complète pour une définition de type sans nom.

C ++ 03 ne possède pas cette formulation explicite, mais indique de la même manière que l’ identifier dans une définition de type est facultatif et fait référence aux “classes non nommées” aux 9.4.2/5 et 3.5/4 .

  • Donc, le MSDN est-il faux et ces choses sont-elles complètement standard?
  • Ou est-ce qu’il y a une certaine subtilité qui me manque entre “structures / classes sans nom” et les mêmes quand elles sont utilisées comme membres, ce qui les empêche d’être couvertes par cette fonctionnalité C ++ 03 / C ++ 11?
  • Est-ce que je manque une différence fondamentale entre “unnamed struct” et “anonymous struct”? Ils ressemblent à des synonymes pour moi.

Tout le texte standard fait référence à la création d’une “structure sans nom”:

 struct { int hi; int bye; }; 

Juste un bon type sympa, sans nom accessible.

De manière standard, il pourrait être instancié en tant que membre comme ceci:

 struct Foo { struct { int hi; int bye; } bar; }; int main() { Foo f; f.bar.hi = 3; } 

Mais un “struct anonyme” est subtilement différent – c’est la combinaison d’une structure sans nom et du fait que vous en sortez magiquement des membres dans l’object parent:

 struct Foo { struct { int hi; int bye; }; // <--- no member name! }; int main() { Foo f; f.hi = 3; } 

Inversez l'intuition , cela ne crée pas simplement une structure non nommée nestede dans Foo , mais vous donne également automatiquement un "membre anonyme" qui rend les membres accessibles dans l'object parent.

C'est cette fonctionnalité qui est non standard. GCC le prend en charge , tout comme Visual C ++. Les en-têtes d'API Windows utilisent cette fonctionnalité par défaut, mais vous pouvez spécifier que vous ne le souhaitez pas en ajoutant #define NONAMELESSUNION avant d'inclure les fichiers d'en-tête Windows.

Comparez avec la fonctionnalité standard des "unions anonymes" qui font une chose similaire:

 struct Foo { union { int hi; int bye; }; // <--- no member name! }; int main() { Foo f; f.hi = 3; } 

Il semble que, bien que le terme "unnamed" se réfère au type (c'est-à-dire "la classe" ou "la structure"), le terme "anonyme" se réfère plutôt au membre instancié réel (en utilisant une ancienne "c'est plus proche de" un object de type struct y "). C'était probablement la racine de votre confusion initiale.

Les éléments que Microsoft appelle des structures anonymes ne sont pas standard. Une structure sans nom est simplement une structure ordinaire sans nom. Il n’y a pas grand chose à faire avec un, sauf si vous définissez également un object de ce type:

 struct { int i; double d; } my_object; my_object.d = 2.3; 

Les unions anonymes font partie de la norme et elles ont le comportement que vous attendez de la description de Microsoft de leurs structures anonymes:

 union { int i; double d; }; d = 2.3; 

La norme parle de syndicats anonymes : [9.5] / 5

Une union de la forme

 union { member-specification } ; 

s’appelle une union anonyme; il définit un object sans nom de type sans nom. La spécification de membre d’une union anonyme ne doit définir que des membres de données non statiques. [Remarque: Les types et fonctions nesteds ne peuvent pas être déclarés dans une union anonyme. —End note] Les noms des membres d’un syndicat anonyme doivent être distincts de ceux de toute autre entité dans le champ d’application de l’union anonyme. Aux fins de la recherche de nom, après la définition d’union anonyme, les membres de l’union anonyme sont considérés comme ayant été définis dans le cadre dans lequel le syndicat anonyme est déclaré. [ Exemple:

 void f() { union { int a; const char* p; }; a = 1; p = "Jennifer"; } 

Ici, a et p sont utilisés comme des variables ordinaires (non membres), mais comme ils sont membres d’union, ils ont la même adresse. —Exemple]

Les structures anonymes dont parle Microsoft sont cette fonctionnalité pour les unions mais appliquées aux structs . N’est-il pas juste une définition sans nom, il est important de noter que les comptes de l’union / struct anonyme sont considérés comme ayant été définis dans la scope dans laquelle l’union / struct anonyme est déclarée.

Pour autant que je sache, il n’existe aucun comportement de ce type pour les structures non nommées dans le standard. Notez que dans l’exemple cité, vous pouvez réaliser des tâches qui ne seraient pas possibles autrement que, par exemple, partager le stockage des variables dans la stack, tandis que les structures anonymes n’apportent rien de nouveau à la table.