Pourquoi ne “définition de type struct { struct S *s; } S;” contenant un pointeur vers un même type de compilation?
Je suis en train de typedef
un struct
qui contient un pointeur vers un autre du même type.
C'est ce que je pensait être la meilleure version:
typedef struct Element
{
char value;
struct Element *next;
} Element;
Pourquoi est-ce une variante de la compilation + exécution?:
typedef struct
{
char value;
struct Element *next;
} Element;
Pour décrire la première je dirais: "Nom struct Element
Element
maintenant" et le second: "Prenez cet anonyme struct
et de l'appeler Element
"
Mais pourquoi ne puis-je encore déclarer un struct Element
(à l'intérieur de la structure (struct) dans le second cas?
(Travail en GCC
et MSVC
)
- dans le second cas, votre *suivant est le fait de tourner dans un struct struct {}, vous avez besoin de lire sur ce type de définir la réalité.
- Remplacement de
struct Element *next;
avecElement *next;
est signalé comme une erreur. Ou tu veux dire quoi? - Ce n'
struct struct {}
veux dire? Dans le second cas,next
est un pointeur versstruct Element
; le problème est questruct Element
est un type incomplète. - Comment version: stackoverflow.com/questions/3988041/...
Vous devez vous connecter pour publier un commentaire.
Dans le premier cas, votre structure a deux noms équivalents:
struct Element
(oùElement
est une structure de la balise) etElement
(oùElement
est un typedef, un alias pour un type existant).Dans le second cas, vous venez de ne pas définir une balise pour la structure. Normalement, ce serait parfaitement valable, mais ici vous êtes en se référant au type qui n'existe pas
struct Element
dans la déclaration de lanext
membre.Dans ce contexte,
struct Element
est un de type incomplète. Vous ne pouvez pas déclarer des objets incomplets types, mais vous pouvez déclarer des pointeurs vers eux.La déclaration
est légal, mais il ne fait pas
next
un pointeur vers la enfermant type. Il en fait un pointeur vers certains type incomplète, et vous ne serez pas en mesure de se référer à elle jusqu'à ce que et à moins que vous déclarez le type complet.Votre deuxième déclaration est l'un de la multitude de choses qui n'ont aucun sens, mais sont toujours légales C.
Vous pourrait considérer l'omission de la définition de type et de constamment se référant au type
struct Element
. Comme beaucoup de gens aiment la commodité d'avoir un seul mot de nom pour un type de structure, mais mon opinion personnelle est qu'il n'y a pas beaucoup d'avantages pour que (à moins que le type est vraiment opaque, c'est à dire, les utilisateurs de ce type ne sait même pas c'est une structure (struct). C'est une affaire de style.Noter que vous devez vous référer au type
struct Element
, pasElement
, dans la définition elle-même, depuis la définition de type nomElement
n'est pas encore visibles.Le fait que la structure de la balise et de la définition de type ont le même nom peut sembler déroutant, mais il est parfaitement legititimate. Struct des balises et des typedefs sont situés dans des espaces de noms (dans le C sens, pas de sens du C++); une structure de balises ne peuvent apparaître immédiatement après l'
struct
mot-clé.Une autre alternative est de séparer la définition de type de la structure définition:
(Vous pouvez utiliser un type incomplète nom dans un
typedef
.)Votre première variante est correct. Votre deuxième variante n'est pas ce qu'il semble faire.
En C, c'est valable pour déclarer un type struct n'importe où, même dans le milieu de déclarer que quelque chose d'autre. (Les règles de portée pour de telles déclarations-en-passant sont confus au point où je ne vais pas essayer de les expliquer -- il suffit de dire que vous devriez éviter de le faire.) C'est pourquoi vous n'obtenez pas une erreur sur la deuxième construire. Mais ce qu'il signifie pour le compilateur est ceci:
Après ce code, le type "struct Element" est complètement indépendants du type "Élément", et n'a pas été complètement déclarés. Si vous tentez de utilisation ce type, par exemple dans
le compilateur ne sera pas heureux:
Une alternative à votre première variante, qui vous permet d'utiliser "Élément" au lieu de "struct Element' partout, y compris à l'intérieur de la définition du type, est
Mais en C il n'y a aucun moyen d'éviter d'avoir à manuellement, assurez-vous que "struct Element" est la même chose que "Élément". Si vous ne voulez pas avoir à traiter avec elle, C++ est en attente pour vous là-bas ⟶
Pour stocker un pointeur vers une struct, le compilateur n'a pas besoin de connaître sa taille ou le contenu, mais seulement la taille du pointeur.
Dans votre premier exemple,
struct Element
est un type incomplète jusqu'à ce que après la définition de la structure, mais qui fonctionne parce que vous êtes seulement de déclarer un pointeur et non une instance de la structure elle-même.Dans votre deuxième exemple, vous ne déclarez pas un
struct Element
structure (struct Element
etElement
ne sont pas la même chose). Bien que vous pouvez toujours inclure le pointeur dans la structure, il ne fait PAS référence au même type, il se réfère à unstruct Element
qui n'a pas été définie. La structure de la définition dans votre définition de type est un anonyme, un struct, de sorte que vous serez en mesure de faire référence àElement
(sans le mot-clé struct) seulement. Donc le deuxième exemple ne fonctionne pas comme prévu.