2009-09-28 10 views
0

J'essaie de comprendre comment allouer un bloc de mémoire dans une fonction et renvoyer un pointeur vers ce bloc via l'un des arguments. C'est un programme en C. Je semble avoir des problèmes. Voici le code:passer un bloc de mémoire à partir d'une fonction

void foo(char *ptr) 
{ 
    if (!(ptr = malloc(size))) 
      printf("error"); 

    /* code here */ 

    printf("buffer address: %i\n", (int)buffer); 
} 

int main() 
{ 
    char *ptr; 
    ptr = NULL; 

    foo(ptr); 

    printf("buffer address: %i\n", (int)buffer); 
} 

Et le résultat est:

buffer address: 142385160 
buffer address: 0 

mais je me attendais quelque chose comme:

buffer address: 142385160 
buffer address: 142385160 

Qu'est-ce que je fais mal?

+1

Je ne crois pas que ce code donne la sortie que vous avez posté. Qu'est-ce que 'buffer' est déclaré être? Qu'est-ce qui change entre 'main' et' foo'? –

+0

vous avez raison, c'est juste pseudo code ... Je pourrais éditer le poste pour vous donner plus d'informations –

+0

Eh bien, soit le code réel, soit le vrai pseudo-code. Une maison à mi-chemin n'est pas très utile. Vous ne pouvez pas "renvoyer" une valeur en tant que paramètre, les paramètres sont transmis par la valeur en C. Quel est le problème avec le renvoi d'une valeur? (Oui, je sais, vous pouvez renvoyer des informations en les stockant à un endroit indiqué par un paramètre si ce paramètre est un pointeur.) Ce n'est pas la même chose que de transmettre des informations via un paramètre lui-même –

Répondre

2

Pointeurs sont des variables. Toutes les variables de C sont passées par valeur. Observer:

void test(int i) 
{ 
    printf("Before: %i\n", i); 
    i = 0; 
    printf("After: %i\n", i); 
} 

int main(void) 
{ 
    int i = 5; 
    printf("Before: %i\n", i); 
    test(i); 
    printf("After: %i\n", i); 
} 

Prints:

Before: 5 
Before: 5 
After: 0 
After: 5 

Pointeurs fonctionnent de la même façon. Changer le pointeur lui-même ne change pas le pointeur de l'appelant. L'avantage des pointeurs est de modifier le contenu du pointeur. Vous avez quelques options:

void foo(char **ptr) 
{ 
    if (!(*ptr = malloc(size))) 
     printf("error"); 

    /* code here */ 

    printf("buffer address: %p\n", ptr); 
} 

int main() 
{ 
    char *ptr; 
    ptr = NULL; 

    foo(&ptr); 

    printf("buffer address: %p\n", *ptr); 
} 

Ou:

char *foo(char *ptr) 
{ 
    if (!(ptr = malloc(size))) 
     printf("error"); 

    /* code here */ 

    printf("buffer address: %p\n", ptr); 
    return ptr; 
} 

int main() 
{ 
    char *ptr; 
    ptr = NULL; 

    ptr = foo(ptr); 

    printf("buffer address: %p\n", ptr); 
} 

que vous utilisez dépend de ce que foo() fait. Choisissez celui qui a le sens le plus logique.

+0

Je supprimerais simplement l'argument de foo du dernier exemple, mais à part ça ça marche! Merci! –

1

Vous devez passer un pointeur vers un pointeur vers un char, comme ceci:

void foo(char **ptr) 
{ 
    // ... 
    *ptr = result of malloc; 
} 

Ou encore mieux, revenir comme ceci:

void char * foo(int memsize) 
{ 

} 
1

Dans votre fonction, vous réaffectez votre copie locale du pointeur. Pour réaffecter le pointeur dans la fonction d'appel, vous devez lui transmettre l'adresse du pointeur, plutôt que l'adresse de celui sur lequel pointe le pointeur.

void foo(char **ptr) 
{ 
    if (!(*ptr = malloc(size))) 
      printf("error"); 

    /* code here */ 

    printf("buffer address: %i\n", (int)*buffer); 
} 

int main() 
{ 
    char *ptr; 
    ptr = NULL; 

    foo(&ptr); // pass address of your ptr, rather than it's value 

    printf("buffer address: %i\n", (int)buffer); 
} 
5

D'autres ont montré le passage d'un pointeur vers un pointeur, mais une option plus simple est indiquée par votre question:

J'essaie de comprendre comment allouer un bloc de mémoire dans une fonction et renvoie un pointeur vers ce bloc.

(moi qui souligne.)

Quand vous pensez à retour quelque chose, essayez de l'utiliser comme la valeur de retour :)

char* foo() 
{ 
    char* ptr; 
    if (!(ptr = malloc(size))) 
     printf("error"); 

    /* code here */ 

    printf("buffer address: %i\n", (int)ptr); 
    return ptr; 
} 

(Vous pouvez également envisager de revenir void* au lieu de char*

Si vous avez déjà une valeur de retour pour une autre raison, puis Il peut être approprié d'utiliser l'approche "pointeur vers un pointeur" - mais si vous n'utilisez pas la valeur d'origine, juste en retournant quelque chose, je crois que cela vaut la peine de garder les choses simples si vous le pouvez.

+0

ok je l'ai changé :) –

+2

+1, mais tant que nous y sommes, je ne recommanderais pas de traiter le pointeur comme un entier. Je ne sais pas à quel point c'est portable, mais '% p' sonne mieux pour moi. –

3

Pourquoi ne pas vous revenez juste un pointeur, autant que vos états de question:

void* foo(void) 
{ 
    void* ptr = malloc(size); 
    if (!ptr) 
      printf("error"); 

    /* code here */ 

    printf("buffer address: %p\n", ptr); 
} 

int main(void) 
{ 
    char *ptr = foo(); 

    printf("buffer address: %p\n", (void*)ptr); 
} 

(Autres modifications que j'ai fait devaient faire en sorte que tous les printf des types de pointeurs utilisés %p et ont été passés un type void* soit en changeant le type d'une variable ou par un cast explicite.J'ai également ajouté des initialisations aux déclarations de variables le cas échéant.)

+1

+1 pour changer '% i' en'% p' ;-) –

3

Eh bien, en supposant que le tampon (int) devrait être (int) ptr, vous passez le pointeur par valeur, pas de référence, donc changé dans la fonction n'ont pas d'effet ide.

Vous pouvez retourner le résultat:

char *foo() 
{ 
    if (!(ptr = malloc(size))) 
      printf("error"); 

    /* code here */ 

    printf("buffer address: %i\n", (int)ptr); 
    return ptr; 
} 

int main() 
{ 
    char *ptr; 
    ptr = NULL; 

    ptr = foo(); 

    printf("buffer address: %i\n", (int)ptr); 
} 

ou passez le pointeur par référence

void foo(char **ptr) 
{ 
    if (!(*ptr = malloc(size))) 
      printf("error"); 

    /* code here */ 

    printf("buffer address: %i\n", (int)*ptr); 
} 

int main() 
{ 
    char *ptr; 
    ptr = NULL; 

    foo(&ptr); 

    printf("buffer address: %i\n", (int)ptr); 
} 
0

Une plus grande simplification pourrait être:

void *fun() 
{ 
    return(malloc(sizeof(char))); 
} 


int main() 
{ 
    char *foo = (char *) fun(); 
    printf("\n%p\n",foo); 
} 
Questions connexes