Je n'écris pas en C depuis très longtemps, donc je ne suis pas sûr de la façon dont je devrais faire ce genre de choses récursives ... Je voudrais que chaque cellule contienne une autre cellule, mais j'obtiens une erreur le long du les lignes du "champ 'enfant' sont de type incomplet". Quoi de neuf?
typedef struct Cell {
int isParent;
Cell child;
} Cell;
Réponses:
Il est clair qu'une cellule ne peut pas contenir une autre cellule car elle devient une récursivité sans fin.
Cependant, une cellule peut contenir un pointeur vers une autre cellule.
la source
Cell
n'est pas encore dans le champ d'application.Cell*
àcell->child
.struct
s en C stockent essentiellement toutes leurs valeurs les unes à côté des autres, il serait impossible de stocker réellement une structure en elle-même (car cette structure devrait en contenir une autre et ainsi de suite, conduisant à une structure mémoire de taille infinie) .struct Cell
, voir cette réponse .En C, vous ne pouvez pas référencer le typedef que vous créez avec la structure elle-même. Vous devez utiliser le nom de la structure, comme dans le programme de test suivant:
Bien que ce soit probablement beaucoup plus compliqué que cela dans le standard, vous pouvez le considérer comme le compilateur connaissant
struct Cell
la première ligne dutypedef
mais ne le sachant pastCell
avant la dernière ligne :-) C'est comme ça que je me souviens de cette règle.la source
Du point de vue théorique, les langues ne peuvent supporter que des structures autoréférentielles et non des structures auto-inclusives.
la source
Il existe une sorte de moyen de contourner cela:
Si vous le déclarez comme ceci, cela indique correctement au compilateur que struct Cell et plain-ol'-cell sont identiques. Vous pouvez donc utiliser Cell comme d'habitude. Il faut encore utiliser struct Cell dans la déclaration initiale elle-même.
la source
struct Cell;
?struct Cell
.struct Cell;
redondant. Si, cependant, pour une raison quelconque, vous mettez les deux dernières lignes dans un fichier d'en-tête que vous incluez avant de définir laCell
structure avec les quatre premières lignes, alors le supplémentstruct Cell;
est nécessaire.typedef struct Cell Cell;
et cela créeraCell
un alias pourstruct Cell
. Peu importe que le compilateur ait déjà vustruct Cell { .... }
.Je sais que cet article est ancien, cependant, pour obtenir l'effet que vous recherchez, vous pouvez essayer ce qui suit:
Dans l'un ou l'autre des deux cas mentionnés dans le fragment de code ci-dessus, vous DEVEZ déclarer votre structure Cell enfant en tant que pointeur. Si vous ne le faites pas, vous obtiendrez l'erreur "le champ" l'enfant "a un type incomplet". La raison est que "struct Cell" doit être défini pour que le compilateur sache combien d'espace allouer lorsqu'il est utilisé.
Si vous essayez d'utiliser "struct Cell" dans la définition de "struct Cell", alors le compilateur ne peut pas encore savoir combien d'espace "struct Cell" est censé prendre. Cependant, le compilateur sait déjà combien d'espace un pointeur prend, et (avec la déclaration forward) il sait que "Cell" est un type de "struct Cell" (bien qu'il ne sache pas encore la taille d'une "struct Cell" ). Ainsi, le compilateur peut définir une "Cell *" dans la structure en cours de définition.
la source
Passons en revue la définition de base de typedef. typedef utilise pour définir un alias vers un type de données existant, qu'il soit défini par l'utilisateur ou intégré.
par exemple
La confusion est ici avec la structure auto-référentielle, due à un membre du même type de données qui n'est pas défini précédemment. Donc, de manière standard, vous pouvez écrire votre code comme suit: -
Mais la dernière option augmente quelques lignes et mots supplémentaires avec généralement nous ne voulons pas faire (nous sommes tellement paresseux vous savez;)). Préférez donc la vue 2.
la source
typedef
syntaxe est incorrecte (considérez par exempletypedef int (*foo)(void);
). Vos exemples View 1 et View 2 ne fonctionnent pas: ils créentstruct Cell
un type incomplet, vous ne pouvez donc pas les utiliserchild
dans votre code.Une autre méthode pratique consiste à pré-typer la structure avec la balise structure comme suit:
la source
Une structure qui contient une référence à elle-même. Une occurrence commune de ceci dans une structure qui décrit un nœud pour une liste de liens. Chaque nœud a besoin d'une référence au nœud suivant de la chaîne.
la source
Toutes les réponses précédentes sont excellentes, j'ai juste pensé à donner un aperçu de la raison pour laquelle une structure ne peut pas contenir une instance de son propre type (pas une référence).
il est très important de noter que les structures sont des types «valeur», c'est-à-dire qu'elles contiennent la valeur réelle, donc lorsque vous déclarez une structure, le compilateur doit décider de la quantité de mémoire à allouer à une instance de celle-ci, il passe donc par tous ses membres et ajoute dans leur mémoire pour comprendre la mémoire totale de la structure, mais si le compilateur a trouvé une instance de la même structure à l'intérieur, alors c'est un paradoxe (c'est-à-dire pour savoir combien de mémoire la structure A prend, vous devez décider de la quantité de mémoire struct A prend!).
Mais les types de référence sont différents, si une structure 'A' contient une 'référence' à une instance de son propre type, bien que nous ne sachions pas encore combien de mémoire lui est allouée, nous savons combien de mémoire est allouée à une mémoire adresse (c'est-à-dire la référence).
HTH
la source