Affectation d’une adresse à un membre du tableau d’un pointeur struct en C

Avoir des problèmes considérables avec une arithmatique de pointeur. Je pense que je comprends les concepts (les variables de pointeur pointent vers une adresse mémoire, les variables normales pointent vers des données) mais je crois que mon problème est lié à la syntaxe ( *, &, (*), *(), etc.)

Ce que je veux faire, c’est construire des tableaux dynamics d’une structure personnalisée (c’est-à-dire des tableaux de pointeurs vers des structures de tas), et mon interface fournit deux méthodes, “ad_to_obj_array” (qui prend l’object à append et le tableau qui peut être null pour vide) et “obj_array_dustbin” (qui amène simplement le tableau à disposer, ainsi que le contenu, les tas objs). Le premier est rendu ci-dessous.

Les détails des objects ne sont pas importants (et la structure a été renommée de toute façon) mais ma solution au problème général est ci-dessous, et je vous serais reconnaissant de bien vouloir repérer l’erreur. Le compilateur se plaint d’une valeur invalide, où j’essaie d’atsortingbuer l’adresse du pointeur du RHS à la valeur du pointeur dans un tableau de pointeurs vers des structures de tas:

 #define NUM_ELEM(x) (sizeof (x) / sizeof (*(x))) obj* add_to_obj_array(obj* new_obj, obj* array) { int number_of_elements = 0; if (array != NULL) { number_of_elements = NUM_ELEM(array); } obj* new_array = NULL; /* note: I am expecting sizeof(new_obj) to return the size of an obj* to go into the array of pointers. */ if ( NULL == (new_array = (obj*)malloc((number_of_elements + 1)* sizeof(new_obj))) ) { /* memory request refused :( */ return NULL; } /* copy the old array pointers into the new array's pointer slots: */ int i; for (i = 0; i  0) { free(&array); } return new_array; } 

Maintenant, j’ai essayé les permutations suivantes de la ligne incriminée:

  &(new_array[i]) = &(array[i]); *(new_array[i]) = &(array[i]); new_array[i] = &(array[i]); 

et tous donnent une erreur de compilation d’une sorte ou d’une autre. Je suis à peu près sûr que le côté droit est l’adresse du ième élément de l’ancien tableau, mais comment puis-je assigner au ième élément du nouveau, lorsque les éléments du tableau sont des pointeurs sur des structures?

EDIT – veuillez noter que la macro NUM_ELEM ci-dessus ne fonctionne pas; 1. Voir la réponse de @Merlyn Morgan-Graham ci-dessous pour savoir pourquoi.

Selon votre description, vous partez mal, de sorte que vous ne pourrez probablement plus rien faire avant de copier des éléments.

À l’heure actuelle, vous avez défini new_array (et probablement un array ) comme un pointeur sur obj . Le résultat ressemble à ceci:

texte alternatif

Dans ce cas, vous avez un pointeur sur un tableau d’objects alloué dynamicment. Lorsque / si vous développez l’allocation, vous devez copier tous les objects eux-mêmes.

Selon votre description: “(c’est-à-dire des tableaux de pointeurs vers des structures de tas)”, ce que vous voulez, c’est un tableau de pointeurs. Si vous souhaitez allouer automatiquement ce tableau de pointeurs, votre définition ressemblerait à ceci:

 obj *array[NUMBER]; 

À mon avis, ce n’est pas ce que vous voulez. Vraisemblablement, vous souhaitez également allouer ce tableau de manière dynamic. Cela ressemblerait à ceci:

texte alternatif

Dans ce cas, new_array et array devront chacun être définis en tant que pointeur à pointer vers obj . Vous alloueriez alors un tableau de pointeurs (c’est-à-dire des pointeurs vers autant d’ obj que vous le souhaitez) et auriez chaque point à un obj :

 obj **new_array; // allocate an array of pointers with space to point at more items: new_array = malloc(sizeof(obj *) * new_elements); // copy the pointers to the current items to the new array: for (i=0; i 

L'avantage de ceci est que lorsque vous effectuez la copie, vous ne copiez que les pointeurs , pas les objects eux-mêmes. Surtout avec de gros objects, cela peut économiser beaucoup d'effort. Le compromis est que l’utilisation d’un élément passe par deux niveaux d’indirection et un par un, de sorte que la référence peut être plus lente (bien que rarement beaucoup plus lente, en particulier sur un processeur relativement performant).

Comme @rerun l'a déjà souligné, dans les deux cas, vous souhaiterez probablement utiliser realloc . Cela pourrait notamment permettre d’étendre une allocation "sur place" et d’éviter de copier les données aussi souvent. Bien sûr, ce n'est pas garanti, mais au moins vous lui donnez une chance; si vous malloc et copiez à chaque fois, vous éliminez même la possibilité de cette optimisation.

Vous avez deux tableaux. new_array[i] = array[i] ne fait pas ce dont vous avez besoin.

  • Avez-vous envisagé de realloc comme solution possible?

Il suffit d’atsortingbuer les valeurs à travers. new_array[i] = array[i] .

Le problème que vous pouvez rencontrer est que, pour que obj* en réalité un tableau de pointeurs , obj doit lui-même être un type de pointeur:

 typedef struct { int value1; } obj_pool; typedef obj_pool* obj; int main(int argc, char* argv[]) { obj_pool pool1; pool1.value1 = 5; obj array[] = { &pool1 }; array[0]->value1 = 16; return 0; } 

Un autre problème que vous rencontrerez une fois que vous aurez cette compilation est celui de sizeof(array) == sizeof(obj*) . NUM_ELEM(array) renverra toujours la même valeur. Cela signifie que vous devrez passer un paramètre size_t array_size à votre fonction.

dans votre code, les éléments du tableau ne sont pas des pointeurs sur la structure, mais des objects de structure. les éléments du tableau this obj ** sont des pointeurs sur la structure obj.

 #define NUM_ELEM(x) (sizeof (x) / sizeof (*(x))) void add_to_obj_array(obj* new_obj, obj** array) { int number_of_elements = 0; if (array != NULL) { number_of_elements = NUM_ELEM(array); } // expand array with one more item array = (obj**)realloc(array, (number_of_elements + 1) * sizeof(new_obj)); if (array == NULL ) { /* memory request refused :( */ return; } // Put new item at the last place on the array array[number_of_elements] = new_obj; } 

Nous avons donc utilisé ici la masortingce (pointeur sur les pointeurs de la structure obj). Lorsque nous ajoutons un nouvel élément, nous développons simplement un tableau existant pour un emplacement et, à cet endroit, nous plaçons un nouvel object structure. Il n’est pas nécessaire de renvoyer une valeur car nous opérons sur les pointeurs des objects et tout changement est effectué sur les objects réels et non sur leurs copies.