Pourquoi une structure est autorisée à avoir un “pointeur sur son propre type” en tant que membre mais pas “un type de structure (un tableau du type)” lui-même?

quand j’essaie de déclarer la fonction suivante

typedef struct TRIE_NODE { char* word; struct TRIE_NODE node[26]; }TRIE_NODE; 

Je reçois l’erreur suivante:

la définition de ‘struct TRIE_NODE’ n’est pas complète avant la fermeture ‘}’

Cependant, si je déclare cette fonction avec un pointeur sur les 26 nœuds, la compilation est parfaite.

 typedef struct TRIE_NODE { char* word; struct TRIE_NODE* node[26]; }TRIE_NODE; 

J’imagine que, puisqu’il ne s’agit pas d’un exemple, il m’est impossible d’obtenir un pointeur sur le premier de ces 26 tableaux, mais si tel est le problème, en quoi le TRIE_NODE* node[26] n’est-il pas aussi un problème? Cette déclaration n’est-elle pas équivalente au TRIE_NODE node[1][26] ?

quand j’essaie de déclarer la fonction suivante

Attendre!! ce n’est pas une fonction, c’est typedef -ing une structure, un type défini par l’utilisateur.


Cela dit, dans le premier cas,

 typedef struct TRIE_NODE { char* word; struct TRIE_NODE node[26]; //array of type struct TRIE_NODE }TRIE_NODE; 

si cela doit être possible, le compilateur doit connaître la taille de la struct TRIE_NODE avant sa définition, ce qui est impossible. Donc, c’est invalide.

D’autre part,

 typedef struct TRIE_NODE { char* word; struct TRIE_NODE* node[26]; //array of pointers (of type struct TRIE_NODE) }TRIE_NODE; 

Si vous allouez (un tableau) de pointeurs à la structure, il n’est pas nécessaire que la taille réelle de la structure soit connue du compilateur à ce stade. Ainsi, le compilateur alloue les pointeurs et la définition (construction) est parfaitement valide.

Pour répondre à votre propre question, demandez: combien d’octets seront

 struct TRIE_NODE node[26]; 

occuper? En fait, qu’attendriez-vous de sizeof(struct TRIE_NODE) ?

La raison

 struct TRIE_NODE *node[26]; 

fonctionne est que nous connaissons la valeur de sizeof(struct TRIE_NODE*) . Étant donné que tous les pointeurs de structure ont la même taille , nous pouvons allouer un tableau de N pointeurs de structure, quel que soit leur type, même s’ils n’ont pas été définis de manière complète.

les pointeurs et les tableaux ne sont-ils pas presque interchangeables?

La syntaxe des pointeurs et des tableaux est similaire. Vous pouvez inscrire un pointeur et append une adresse à un tableau. Mais ils définissent des choses différentes. Fondamentalement: un tableau contient des données et un pointeur contient une adresse.

Dans certaines parties de la bibliothèque standard C, vous trouverez des structures définies comme suit:

 struct S { int len; char data[1]; }; 

Vous pourriez être tenté de demander pourquoi ne pas utiliser un pointeur?

 struct Z { int len; char *data; }; 

Réponse: la struct S est en réalité plus grande que les 5 octets ou plus qu’elle semble occuper, et la partie de données commence immédiatement après len . Dans l’exemple de struct Z putatif, les data ne commencent pas les données; les données seraient ailleurs, où que soient data points de data .

En supposant que les structures soient initialisées de manière appropriée, dans les deux cas, data[0] adressera le premier octet du tableau. Ils sont syntaxiquement similaires. Mais la disposition de la mémoire est différente. Dans le cas S , cet octet sera assez proche de (char*)&len + sizeof(len) . Dans le cas Z ce sera où data points de data .

Personne ne le mentionne, mais si struct était autorisé à avoir un membre ou un tableau de lui-même (pas un pointeur, mais un membre régulier ou un tableau), alors la structure serait récursive et d’une taille infinie, car le membre aurait un membre supplémentaire à l’intérieur tapez et ainsi de suite jusqu’à l’infini.