C: ajout d’un élément à un tableau alloué dynamicment

J’ai essayé de rechercher une solution via Google: je n’ai rien trouvé qui puisse m’aider; il semblait même que je le faisais correctement. Les seules pages que j’ai pu trouver concernant l’envoi de mon tableau alloué dynamicment via une fonction traitant du tableau dans une structure, qui est scalaire bien sûr, se comportent donc différemment. Je ne veux pas utiliser de structure pour le moment – j’essaie d’en savoir plus sur DAM et de travailler avec des pointeurs et des fonctions.

Cela dit, je suis sûr que c’est très élémentaire, mais je suis coincé. Le code est compilé, mais il se fige lorsque je lance l’exécutable. (J’utilise minGW gcc, si cela compte. Et je ne suis pas du tout clair sur l’utilisation de gdb.)

Voici le code (à terme, je veux que tout le code soit une structure de données semblable à ArrayList):

#include  #include  void add( int element, int *vector); void display_vector( int *vector ); void initialize_vector( int *vector ); int elements = 0; int size = 10; int main(void) { int *vector = 0; initialize_vector(vector); add(1, vector); //add(2, vector); //add(3, vector); //add(4, vector); //add(5, vector); //add(6, vector); //add(7, vector); //add(8, vector); //add(9, vector); //add(10, vector); //add(11, vector); display_vector(vector); return 0; } void add( int element, int *vector) { vector[elements++] = element; return; } void display_vector( int *vector ) { int i; for( i = 0; i < elements; i++) { printf("%2d\t", vector[i]); if( (i + 1) % 5 == 0 ) printf("\n"); } printf("\n"); return; } void initialize_vector( int *vector ) { vector = (int *)malloc(sizeof(int) * size); } 

Edité pour rendre un peu plus clair.

Le problème est que votre routine d’initialisation travaille avec une copie de «vecteur» et se moque de cette copie plutôt que du pointeur de vecteur original. Vous perdez le pointeur sur le bloc de mémoire au retour de l’initialisation.

Remplace le paramètre du vecteur par une poignée (pointeur à pointeur) dans cette fonction

 void initialize_vector( int **vector ) { *vector = (int *)malloc(sizeof(int) * size); } 

Puis changez l’appel pour init

 initialize_vector(&vector); 

Je n’ai pas compilé ceci, mais cela devrait corriger le code.

En C, les arguments de fonction sont passés par valeur, ce qui signifie qu’il existe une copie locale pour chaque argument passé à une fonction. Si vous modifiez un argument dans une fonction, vous ne modifiez que la copie locale de cet argument. Donc, si vous voulez changer la valeur d’un argument dans une fonction, vous devez lui donner l’adresse, déréférencer cette adresse et affecter le résultat à cette fonction.

Assez pour la théorie, voici comment corriger votre code:

 void initialize_vector( int **vector ); initialize_vector(&vector); void initialize_vector( int **vector ) { *vector = (int *)malloc(sizeof(int) * size); } 

En plus d’autres réponses, je suggérerais une autre approche.

En supposant au moins un compilateur conforme à C99 , je suggérerais plutôt de conserver la taille allouée dans un membre d’une structure se terminant par un membre de tableau flexible (voir aussi ceci ) comme ceci :

  typedef struct vector_st { unsigned count; // used length unsigned size; // allocated size, always >= length int vectarr[]; } Vector; 

Ensuite, vous construirez un tel vecteur avec

  Vector* make_vector (unsigned size) { Vector* v = malloc(sizeof(Vector)+size*sizeof(int)); if (!v) { perror("malloc vector"); exit (EXIT_FAILURE); }; memset (v->vectarr, 0, size*sizeof(int)); v->count = 0; v->size = size; } 

Pour append un élément dans un vecteur, renvoyer le vecteur d’origine ou un vecteur développé:

 Vector* append_vector (Vector*vec, int elem) { assert (vec != NULL); unsigned oldcount = vec->count; if (oldcount < vec->size) { vec->vectarr[vec->count++] = elem; return vec; } else { unsigned newsize = ((4*oldcount/3)|7) + 1; Vector* oldvec = vec; vec = malloc(sizeof(Vector)+newsize*sizeof(int)); if (!vec) { perror("vector grow"); exit(EXIT_FAILURE); }; memcpy (vec->vectarr, oldvec->vectarr, oldcount*sizeof(int)); memset (vec->vectarr + oldcount, 0, (newsize-oldcount) * sizeof(int)); vec->vectarr[oldcount] = elem; vec->count = oldcount+1; vec->size = newsize; free (oldvec); return vec; } } 

et vous pourriez coder:

 Vector* myvec = make_vector(100); myvec = append_vector(myvec, 35); myvec = append_vector(myvec, 17); for (int i=0; i<150; i++) myvec = append_vector(myvec, i*2); 

Pour libérer un tel vecteur, utilisez simplement free(myvec);


Si vous ne voulez vraiment pas utiliser de struct vous devriez garder dans des variables séparées la longueur utilisée de votre vecteur, la taille allouée de votre vecteur, le pointeur sur votre tableau alloué dynamicment:

  unsigned used_count; // useful "length" unsigned allocated_size; // allocated size, always not less than used_count int *dynamic_array; // the pointer to the dynamically allocated array 

Si vous voulez pouvoir gérer plusieurs vecteurs, vous devez regrouper la longueur utile ci-dessus, la taille allouée et le tableau dynamic dans une struct dynamic_array_st (dont le pointeur est transmis aux routines appropriées, telles que make_dynamic_vector(struct dynamic_array_st*) , append_dynamic_vector(struct dynamic_array_st*, int) , etc ....) ou bien transmettez-les sous trois formelles distinctes à des routines similaires, puis vous devrez passer leur adresse, car les routines les modifieraient, par exemple create_dynamic_vector(unsigned *countptr, unsigned *sizeptr, int**vectarrptr) que vous invoqueriez en tant que create_dynamic_vector(&mycount, &mysize, &myvectarr); etc.

Je pense effectivement qu'un membre de groupe flexible rest l'approche la plus propre.