web-dev-qa-db-fra.com

renvoyer une variable locale de la fonction en C

#include <stdio.h>

int foo1(void)
{
    int p;
    p = 99;
    return p;
}

char *foo2(void)
{
    char buffer[] = "test_123";
    return buffer;
}

int *foo3(void)
{
    int t[3] = {1,2,3};
    return t;
}

int main(void)
{
    int *p;
    char *s;

    printf("foo1: %d\n", foo1());
    printf("foo2: %s\n", foo2());
    printf("foo3: %d, %d, %d\n", p[0], p[1], p[2]);
    return 0;
}

Quand je compile ceci avec gcc -ansi -pedantic -W -Wall le compilateur émet des messages d'avertissement pour foo2 () et foo3 ():

warning: function returns address of local variable

Je pensais qu'il n'est pas autorisé de retourner une variable locale, mais foo1 () fonctionne très bien et il semble qu'il y ait une énorme différence entre le retour d'un pointeur vers un objet local et l'objet lui-même.

Quelqu'un pourrait-il faire la lumière sur cette question? Merci d'avance!

34
Mark

Le problème ici est que lorsque vous créez la variable locale, elle est allouée sur la pile et n'est donc pas disponible une fois l'exécution de la fonction terminée (l'implémentation varie ici). La manière préférable serait d'utiliser malloc() pour réserver de la mémoire non locale. le danger ici est que vous devez désallouer (free()) tout ce que vous avez alloué en utilisant malloc(), et si vous oubliez, vous créez une fuite de mémoire.

24
kelloti

Pour foo1(), vous retournez un copie de la variable locale, pas la variable locale elle-même.

Pour les autres fonctions, vous renvoyez une copie d'un pointeur vers une variable locale. Cependant, cette variable locale est désallouée lorsque la fonction se termine, vous vous retrouvez donc avec des problèmes désagréables si vous essayez de la référencer par la suite.

18
Cam

Toute variable a de l'espace dans la mémoire. Un pointeur fait référence à cet espace. L'espace occupé par les variables locales est désalloué lorsque l'appel de fonction revient, ce qui signifie qu'il peut et sera réutilisé pour d'autres choses. En conséquence, les références à cet espace vont finir par pointer vers quelque chose de complètement indépendant. Les tableaux en C sont implémentés en tant que pointeurs, donc cela finit par s'appliquer à eux. Et les tableaux constants déclarés dans une fonction comptent également comme étant locaux.

Si vous souhaitez utiliser un tableau ou un autre pointeur au-delà de la portée de la fonction dans laquelle il est créé, vous devez utiliser malloc pour lui réserver de l'espace. L'espace réservé à l'aide de malloc ne sera pas réalloué ou réutilisé tant qu'il ne sera pas explicitement libéré en appelant free.

5
Keith Irwin

Oui, vous renvoyez un tableau, qui est en fait un pointeur en arrière-plan, à l'adresse de l'emplacement de mémoire où le contenu de la variable que vous avez initialisé est stocké. Il vous avertit donc qu'il ne serait peut-être pas aussi utile de renvoyer un tel résultat, alors que vous pourriez vraiment vouloir dire l'une des valeurs du tableau à la place.

0
evandrix