Comme pour tout ce qui semble plus effrayant au début qu'il ne l'était plus tard, le meilleur moyen de surmonter la peur initiale est de se plonger dans l'inconfort de l'inconnu ! C'est parfois comme cela que nous apprenons le plus, après tout.
Malheureusement, il existe des limites. Pendant que vous apprenez encore à utiliser une fonction, vous ne devriez pas assumer le rôle d'un enseignant, par exemple. Je lis souvent les réponses de ceux qui ne savent apparemment pas comment utiliser realloc
(c'est-à - dire la réponse actuellement acceptée! ) En disant aux autres comment l'utiliser de manière incorrecte, parfois sous prétexte qu'ils ont omis la gestion des erreurs , même si c'est un écueil courant qui doit être mentionné. Voici une réponse expliquant comment l'utiliser realloc
correctement . Notez que la réponse stocke la valeur de retour dans une variable différente afin d'effectuer une vérification des erreurs.
Chaque fois que vous appelez une fonction et chaque fois que vous utilisez un tableau, vous utilisez un pointeur. Les conversions se produisent implicitement, ce qui devrait être encore plus effrayant, car ce sont les choses que nous ne voyons pas qui causent souvent le plus de problèmes. Par exemple, des fuites de mémoire ...
Les opérateurs de tableau sont des opérateurs de pointeur. array[x]
est en fait un raccourci pour *(array + x)
, qui peut être décomposé en: *
et (array + x)
. Il est fort probable que ce *
soit ce qui vous trouble. Nous pouvons en outre éliminer l'addition du problème en supposant x
être 0
, ainsi, array[0]
devient *array
parce que l'ajout 0
ne changera pas la valeur ...
... et ainsi nous pouvons voir que cela *array
équivaut à array[0]
. Vous pouvez en utiliser un là où vous souhaitez utiliser l'autre, et vice versa. Les opérateurs de tableau sont des opérateurs de pointeur.
malloc
, realloc
et les amis n'inventent pas le concept de pointeur que vous utilisez depuis le début; ils l' utilisent simplement pour implémenter une autre fonctionnalité, qui est une forme différente de durée de stockage, la plus appropriée lorsque vous souhaitez des changements de taille drastiques et dynamiques .
Il est dommage que la réponse actuellement acceptée va également à l'encontre de certains autres conseils très fondés sur StackOverflow , et en même temps, manque une occasion d'introduire une fonctionnalité peu connue qui brille exactement pour ce cas d'utilisation: le tableau flexible. membres! C'est en fait une réponse assez cassée ... :(
Lorsque vous définissez votre struct
, déclarez votre tableau à la fin de la structure, sans aucune limite supérieure. Par exemple:
struct int_list {
size_t size;
int value[];
};
Cela vous permettra d'unir votre tableau int
dans la même allocation que la vôtre count
, et les relier comme ça peut être très pratique !
sizeof (struct int_list)
agira comme s'il value
avait une taille de 0, donc il vous indiquera la taille de la structure avec une liste vide . Vous devez encore ajouter à la taille passée à realloc
pour spécifier la taille de votre liste.
Un autre conseil pratique est de se souvenir que cela realloc(NULL, x)
équivaut à malloc(x)
, et nous pouvons l'utiliser pour simplifier notre code. Par exemple:
int push_back(struct int_list **fubar, int value) {
size_t x = *fubar ? fubar[0]->size : 0
, y = x + 1;
if ((x & y) == 0) {
void *temp = realloc(*fubar, sizeof **fubar
+ (x + y) * sizeof fubar[0]->value[0]);
if (!temp) { return 1; }
*fubar = temp; // or, if you like, `fubar[0] = temp;`
}
fubar[0]->value[x] = value;
fubar[0]->size = y;
return 0;
}
struct int_list *array = NULL;
La raison pour laquelle j'ai choisi d'utiliser struct int_list **
comme premier argument peut ne pas sembler immédiatement évidente, mais si vous pensez au deuxième argument, toute modification apportée value
de l'intérieur push_back
ne serait pas visible pour la fonction à partir de laquelle nous appelons, n'est-ce pas? Il en va de même pour le premier argument, et nous devons être en mesure de modifier notre array
, non seulement ici mais peut-être aussi dans toute autre fonction à laquelle nous le passons ...
array
commence par ne pointer du doigt rien; c'est une liste vide. L'initialiser équivaut à l'ajouter. Par exemple:
struct int_list *array = NULL;
if (!push_back(&array, 42)) {
// success!
}
PS N'oubliez pasfree(array);
quand vous en avez terminé!