6
votes

Mémoire dynamique créée dans une fonction

J'aimerais connaître la raison technique (en termes de mémoire) Pourquoi ce code ne fonctionnera pas:

#include <stdio.h>
#include <stdlib.h>

int* fun(int*);
int main()
{
  int a=5;
  int* ptr;
  //  ptr=(int*)malloc(sizeof(int));
  fun(ptr);
  a=*ptr;

  printf("\n the val of a is:%d",a);
  return 0;
}

void fun(int* ptr)
{

  ptr = (int*)malloc(sizeof(int));
  *ptr = 115;


}


2 commentaires

+1, au fait, pour une question claire et précise.


+1 C'est une erreur extrêmement courante, je me souviens de faire la même chose même il y a longtemps (dans une galaxie bien loin;)


7 Réponses :


1
votes

Vous devez transmettre l'adresse du pointeur dans la principale si vous souhaitez le modifier: xxx

(et modifier amusant de manière appropriée, bien sûr)

Pour le moment, il change la variable locale PTR à l'intérieur de la fonction et, bien sûr, ce changement n'apparaît pas comme par magie ailleurs.


0 commentaires

3
votes

Le paramètre amusant () code> est une copie de la variable que vous avez transmise à amusement () code>. Donc, lorsque vous faites:

int* fun(int** ptr) 
{ 
     *ptr = (int*)malloc(sizeof(int)); 
     **ptr = 115; 
} 


2 commentaires

@shachartooth: Oui, ce sera une valeur de réussite dans le cas où Malloc est à l'intérieur du plaisir (). Mais il serait toujours une valeur de passage si le malloc est fabriqué en main (). Pourriez-vous s'il vous plaît dites-moi pourquoi on fonctionnerait et une fois?


Parce qu'en un, vous initialisez le pointeur pour pointer vers la bonne mémoire, puis copiez le pointeur et définissez ce que la copie pointe sur à 115. Dans l'autre, vous copiez le pointeur ininitialisé, initialisez la copie au point à la bonne mémoire, et définir ce que la copie pointe à 115. La différence dans le second cas est que Le pointeur d'origine est toujours ininitialisé



0
votes

Vous passez le PTR par valeur sur amusant . amusant recevra une copie de PTR qui sera modifié. Vous devez passer PTR comme int ** . xxx

et appelez-le avec: xxx

(j'ai également supprimé la valeur de retour de amusant car il n'a pas été utilisé)


1 commentaires

@Andreas: Oui, ce sera une valeur de réussite dans le cas où Malloc est à l'intérieur du plaisir (). Mais il serait toujours une valeur de passage si le malloc est fabriqué en main (). Pourriez-vous s'il vous plaît dites-moi pourquoi on fonctionnerait et une fois?



0
votes

La variable int * pTR est transmis par la valeur à la fonction amusant . Donc, la valeur attribuée à PTR à l'intérieur de la fonction à l'aide de pTR = (int *) malloc (tailleof (int)); ne sera pas reflété en dehors de la fonction. Donc, lorsque vous faites a = * ptr; dans principal () Vous essayez d'utiliser un pointeur non initialisé. Si vous souhaitez refléter les modifications apportées à PTR en dehors de la fonction, vous devez modifier la signature de l'amusement à amusant (int ** ptr) et faire * ptr = (int *) malloc (taille de (int));


0 commentaires

15
votes

en C, Tout est passé par la valeur .

Ce que vous passez à l'amusement () est une copie du pointeur que vous avez dans Main ().

cela signifie que la copie de PTR est destinée à la mémoire allouée et que la mémoire définie sur 115.

Le PTR dans la principale () reste sur un emplacement indéfini car il n'a jamais été attribué.

Essayez de passer un pointeur sur le pointeur , de sorte que dans amusant () Vous avez accès au Pointeur lui-même: xxx

L'autre option serait de faire amusant () renvoie effectivement le pointeur mis à jour (comme annoncé) et attribuer ceci à PTR : xxx

edit: j'ai renommé la variable dans amusement () pour préciser que c'est Différent de celui que vous utilisez dans principal () . Même nom ne veut rien dire ici.


5 commentaires

@DevSolar: Oui, ce sera une valeur de réussite dans le cas où Malloc est à l'intérieur du plaisir (). Mais il serait toujours une valeur de passage si le malloc est fabriqué en main (). Pourriez-vous s'il vous plaît dites-moi pourquoi on fonctionnerait et une fois?


tout passe par valeur! Re-lisez la première ligne.


Dans votre code: Disons que vous initialiseriez PTR dans Main (), à 0x12345678 ou autre. Vos appels de ligne commentés MALLOC () et attribuent sa valeur de retour à PTR , ce qui fait le point sur l'emplacement de la mémoire alloué par Malloc (). - Votre fonction amusement () , en contraste, reçoit une copie de PTR (pointant sur 0x12345678), appels MALLOC ( ) attribue sa valeur de retour à la copie de PTR et retourne. (À tort sans retourner le int * comme annoncé.) Une fois la fonction renvoie, vous travaillez à nouveau sur le réel PTR - qui pointe toujours pour 0x12345678 ...


Voir aussi la réponse mise à jour.


@DevSolar: Wow, j'ai oublié complètement la déclaration de retour. Désolé, ça ... et merci beaucoup. J'étais enfermé pour trouver la réponse sans utiliser des doubles pointeurs.



2
votes

Vous êtes confus à propos de plusieurs choses ici, mais une manière facile d'écrire la fonction est la suivante:

int * ip;
fun( & ip );
printf( "%d", * ip );
free( ip );


0 commentaires

0
votes

N'oubliez pas que si vous souhaitez qu'une fonction modifie la valeur d'un argument, vous devez transmettre un pointeur sur cet argument. Ceci s'applique aux valeurs du pointeur; Si vous souhaitez que une fonction modifie une valeur de pointeur (pas ce que le pointeur pointe vers), vous devez transmettre un pointeur sur ce pointeur:

void fun (int **ptr)
{
  /**
   * Do not cast the result of malloc() unless you are 
   * working with a *very* old compiler (pre-C89).  
   * Doing so will supress a valuable warning if you 
   * forget to include stdlib.h or otherwise don't have 
   * a prototype for malloc in scope.
   *
   * Also, use the sizeof operator on the item you're
   * allocating, rather than a type expression; if you
   * change the base type of ptr (say from int to long),
   * then you don't have to change all the corresponding
   * malloc() calls as well.
   *
   * type of   ptr = int **
   * type of  *ptr = int *
   * type of **ptr = int
   */  
  *ptr = malloc(sizeof **ptr);
  *ptr = 115;
}

int main(void)
{
  int *p;
  fun(&p);
  printf("Integer value stored at %p is %d\n", (void *) p, *p);
  return 0;
}


0 commentaires