Allouer de la mémoire pour un pointeur sur une structure dans une fonction

J’essaye d’écrire un programme séparé qui appelle une fonction pour allouer dynamicment de la mémoire à un certain nombre de structures “student”.

Mon programme principal était trop volumineux, alors j’ai créé un programme plus petit pour m’aider à comprendre plus facilement ce que je fais:

#include  #include  #include  #include "memtest.h" void structMemInit(myName **); int main(void){ myName *myNameIs; structMemInit(&myNameIs); printf("%s\n", myNameIs[1].name); return 0; } void structMemInit(myName **myNameIs){ *myNameIs = (myName *) calloc(5, sizeof(myName)); if(myNameIs == NULL){ printf("allocating memory didn't work!\n"); exit(1); } else if(myNameIs != NULL) (*myNameIs)[1].name = "Zach"; } 

le fichier memtest.h est:

 typedef struct{ char *name; }myName; 

Tout ce que le programme ci-dessus tente de faire est de passer un pointeur sur une structure dans la fonction “structMemInit” et d’allouer de l’espace vide à cette structure. Ensuite, pour voir que cela a fonctionné, je donne à la variable char un nom. Après tout cela, vous quittez la fonction et revenez à main. Ensuite, j’imprime le nom dans la structure pour montrer que cela a fonctionné.

Lorsqu’il est exécuté, le programme donne toujours une erreur de segmentation.

Dans le cas où vous vous demandez pourquoi j’ai un fichier .h séparé, mon programme actuel est beaucoup plus volumineux et comporte plusieurs structures déclarées globalement. Mon instructeur me demande de conserver un fichier .h séparé pour ces structures.

Merci! Zach

Si vous insistez pour passer le pointeur, cela doit être par référence, donc c’est un pointeur sur un pointeur, car la fonction itslef modifiera l’adresse dans le pointeur.

Vous êtes bien mieux si votre fonction renvoie un pointeur.

 //function for allocating the memory myName *structMemInit(void) { myName *myNameIs = (myName *)calloc(1, sizeof(myName)); if (myNameIs == NULL) { printf("allocating memory didn't work!\n"); exit(1); } else { // don't repeat the negation of the condition myNameIs->name = "Zach"; // No need for \0, it's automatic return myNameIs; } } //Usage myName *myNameIs = structMemInit(); 

BTW c’est int main(void) pas int main() .

Avant de répondre, je dois dire que je ne suis pas trop au courant de C, je suis un programmeur C ++ et il peut donc y avoir quelques erreurs grammaticales dans ce qui suit. J’espère cependant que mon argument sera suffisamment clair pour que toute erreur soit d’une grande importance.

La raison pour laquelle vous obtenez une erreur de segmentation est due à votre incompréhension de ce qui se passe lorsque vous passez un pointeur en tant qu’argument d’une fonction.

Imaginez, par exemple, votre programme était le suivant:

 int main(void){ int i; setInteger(i); printf("%d\n", i); return 0; } void setInteger(int n){ n = 12; } 

Dans ce cas, vous pouvez clairement voir que la sortie sera indéfinie car la variable i n’a pas été initialisée et a été transmise par valeur à setInteger . Les modifications apscopes à n ne sont pas retransférées vers i lorsque la fonction revient.

Si le programme était remplacé par

 int main(void){ int i; setInteger(&i); printf("%d\n", i); return 0; } void setInteger(int *n){ *n = 12; } 

Ensuite, la valeur en sortie de i sera 12 .

La même chose se passe dans votre programme, vous passez votre pointeur par valeur .

Si vous souhaitez passer par référence, vous devez procéder comme suit:

 int main(void){ myName *myNameIs; structMemInit(&myNameIs); // pass the address of your pointer printf("%s\n", myNameIs->name); return 0; } //function for allocating the memory void structMemInit(myName **myNameIs){ // argument is pointer-to-pointer *myNameIs = (myName *) calloc(1, sizeof(myName)); // dereference pointer to get underlying pointer if(*myNameIs == NULL){ printf("allocating memory didn't work!\n"); exit(1); } else{ *myNameIs->name = "Zach"; } } 

Malheureusement, ce n’est pas la fin de vos problèmes. Bien que vous ayez alloué de la mémoire à votre object myName , vous n’avez pas alloué de mémoire à votre tableau de caractères.

Pour renvoyer la chaîne “Zach”, vous devez procéder comme suit:

 *myNameIs->name = (char*)malloc(5*sizeof(char)); // need extra char for \0 strcpy(*myNameIs->name, "Zach"); 

Veuillez noter que:

 typedef struct{ char name[20]; } myName; 

est différent de:

 typedef struct{ char *name; } myName; 

Dans le second formulaire, vous n’allouez aucun espace pour la chaîne. Vous allouez simplement de l’espace pour un pointeur.

Vous trouverez ci-dessous une version en cours de votre programme. Si vous voulez utiliser strcpy(p->name, "Zach"); vous devez utiliser le char name[20]; dans votre struct.

 #include  #include  #include  typedef struct{ // char name[20]; char *name; } myName; myName *structMemInit(); int main(){ myName *myNameIs; myNameIs = structMemInit(); if (myNameIs) printf("%s\n", myNameIs->name); return 0; } //function for allocating the memory myName *structMemInit(){ myName * p = (myName *) malloc(sizeof(myName)); if (p == NULL){ fprintf(stderr, "allocating memory didn't work!\n"); } else { fprintf(stderr, "allocating %d memory work!\n", sizeof(myName)); // strcpy(p->name, "Zach"); p->name = strdup("Zach"); } return p; }