Comment dois-je malloc / realloc avec une structure qui inclut un tableau?

Je suis assez nouveau pour c, donc si mes pas sont faux, s’il vous plaît faites le moi savoir Disons que j’ai quelque chose comme ce qui suit:

struct graphNode{ int val; graphNode* parent; int succSize; int succMaxSize; graphNode* succ[1]; }; 

Je vais créer un nouveau noeud avec:

 graphNode *n; n = malloc(sizeof(struct graphNode)); assert(n); n->val = 1; n->parent = NULL; n->succSize = 0; n->succMaxSize = 1; 

Ensuite, si je veux append un successeur au noeud

 if (n->succSize == n->succMaxSize){ n->succ = realloc(n->succ, sizeof(graphNode*) * n->succMaxSize * 2); n->succMaxSize *= 2; } n->succ[succSize] = n2; //n2 is of type graphNode* succSize++; 

Est-ce correct? Ai-je besoin de realloc pour la structure également ou est-ce que realloc du tableau est suffisant? Dois-je malloc pour le tableau initial? La taille de la masortingce initiale doit-elle être incluse dans mon appel malloc pour n?

La manière habituelle de définir un membre de tableau “extensible” en C consiste à spécifier une taille 0 ou non à 0 , par exemple:

 struct foo { int stuff; bar theBars[]; // or theBars[0] }; 

Avec cette définition, sizeof(struct foo) inclura tous les éléments autres que le tableau à la fin, et vous pouvez allouer la bonne taille en disant malloc(sizeof(struct foo) + numberOfBars * sizeof(bar)) .

Si vous devez le réaffecter pour modifier le nombre d’éléments de bar , vous utiliserez la même formule (mais avec un nouveau nombre numberOfBars ).

Pour être clair, vous ne pouvez pas simplement realloc partie d’une structure. Vous devez realloc le tout.

realloc(ptr,size) besoin de 2 parameters, et non de celui utilisé dans realloc(sizeof(graphNode*) * n->succMaxSize * 2)

 // Something like ... graphNode *n; n->succSize = 0; n->succMaxSize = 0; // set to 0 n->succ = NULL; // Initialize to NULL // Then, if OP wants to add a successor to the node if (n->succSize <= n->succMaxSize){ n->succ = realloc(n->succ, sizeof(graphNode*) * n->succMaxSize * 2); n->succMaxSize *= 2; } n->succ[succSize++] = n2; 

Comme pour toutes les allocations de mémoire, vérifiez le retour NULL . Dans realloc() , il convient de sauvegarder la valeur d’origine. Ainsi, si realloc() échoue, le pointeur d’origine n’est pas perdu.

Habituellement, lorsque vous voyez une définition de structure où le dernier champ est un tableau de taille 0 ou 1, cela signifie que l’auteur va faire des choses subtiles avec malloc lorsque la structure est mallocée.

Par exemple

 struct foo { int x; : : type a[0]; }; 

Avec un malloc comme

  struct foo *p = malloc(sizeof(*p) + (n * sizeof(type)); 

Cela alloue un bloc de mémoire contigu à la structure et au tableau de fin. Dans ce cas, la taille du tableau est n. Donc, les références au tableau dans ce cas sont:

 p->a[i] // where i >= 0 and i < n 

Une des raisons est la sauvegarde de la mémoire.

Je suis sûr qu'il existe de meilleures explications à cela sur StackOver; c'est un langage C très commun.

Il n'est généralement pas utilisé lorsque le tableau est dynamic. Au lieu de cela, il est utilisé lorsque la taille du tableau est connue au moment de malloc (). Vous pouvez utiliser de manière dynamic, bien sûr, mais vous devez réaffecter la totalité de la mémoire, pas seulement la structure ou le tableau. Pour augmenter la taille à 2n vous diriez

  p = realloc(p, sizeof(*p) + (2 * n * sizeof(type))); 

Maintenant, votre tableau est deux fois plus gros qu’il était, et c’est toujours un morceau de mémoire.

Si vous ne voulez qu’un seul tableau, faites simplement succ un pointeur et utilisez uniquement malloc / realloc, etc. pour allouer de la mémoire au tableau.

 graphNode* succ; 

Ce que vous faites est presque certain de casser.

Moi aussi, je suis nouveau en C, mais il y a certaines choses que je peux voir d’emblée. Tout d’abord, vous ne pouvez pas réaffecter des tableaux. Dans c89, ils sont à la compilation-taille fixe. En C99 et C11, ils peuvent être alloués de manière dynamic, mais pas réaffectés (à ma connaissance). Donc, pour cela, vous devez allouer un

 graphnode *succ; 

pointeur, et malloc (nœuds * sizeof (nœud)).

 graphNode* succ[1]; 

Cela crée un tableau de taille un, pas un tableau avec un index maximum de un. Donc, c’est la même (presque) fonctionnellement que

 graphNode* succ; 

sauf que vous ne pouvez pas changer sa taille une fois que vous l’avez faite.

Je pense que ce que vous voulez, c’est créer un arbre, avec un nombre de twigs pouvant être redissortingbué de manière dynamic. Dans ce cas, il vous suffit de réaffecter la taille du pointeur graphNode *, puis d’accéder à chaque élément via un index comme vous le feriez d’un tableau.