2
votes

Puis-je renvoyer l'adresse d'une variable dans une fonction de pointeur de type de retour?

J'essaie de comprendre comment fonctionne le pointeur vers une variable et l'adresse d'une variable.

Lorsque j'écris le code suivant:

0060FED8,0060FED8
Process returned -1073741819 (0xC0000005)   execution time : 8.332 s

Sortie:

warning: function returns address of local variable [-Wreturn-local-addr]

L'adresse et le pointeur vers x donnent la même chose valeur, mais lorsque je renvoie l'adresse & x au lieu du pointeur p , le code n'imprime plus la valeur de x :

#include<stdio.h>
int* g(void){
    int x = 10;
    int *p = &x;
    printf("%p,%p",p,&x);
    return (&x);
}
void main(){
    int * p = g();
    printf("\n%d",*p);
}

Avertissement :

0060FED8,0060FED8
10
Process returned 3 (0x3)   execution time : 0.031 s

Résultat: p>

#include<stdio.h>
int* g(void){
    int x = 10;
    int *p = &x;
    printf("%p,%p",p,&x);
    return (p);
}
void main(){
    int * p = g();
    printf("\n%d",*p);
}

Quelqu'un peut-il me dire ce que je fais mal?

c

4 commentaires

Vous ne pouvez pas renvoyer un pointeur vers une variable automatique, car il est nettoyé lorsque la fonction revient, ce cadre de pile a disparu.


accéder à (l'ancienne) adresse d'une variable locale qui est sortie de la portée est un comportement indéfini. Cette question est balisée c ++, mais c'est le même concept en c. La réponse principale est une bonne analogie: stackoverflow.com/questions/6441218/...


Notez que même si la réponse renvoie un pointeur vers le premier élément d'un tableau, tout ce qui s'y trouve s'applique de la même manière que pour toutes les intentions et fins & x est considéré comme un pointeur du premier élément vers un tableau de longueur 1.


En fait, vous pouvez renvoyer un pointeur vers une variable locale, et rien de mal ne se produit à cause de cela. Les mauvaises choses ne se produisent que si vous essayez d'utiliser la valeur de retour de quelque manière que ce soit. C'est comme viser le pistolet sur votre pied - rien de mal ne se passe tant que vous n'appuyez pas sur la détente.


3 Réponses :


0
votes

Puisque x n'est pas alloué de mémoire sur le tas avec malloc ou calloc, il est à la place alloué sur ce qu'on appelle la pile. La pile est principalement utilisée pour les variables locales. Une variable locale n'existe que dans la portée déclarée. Une portée est en termes d'homme pauvre, n'importe quoi entre deux ensembles d'accolades correspondantes.

int* g(void){
    //x is allocated on the stack, since malloc wasn't used
    int x = 10;
    //p is pointing to x's spot in memory (on the stack)
    int *p = &x;
    //These addresses are the same, all is well so far
    printf("%p,%p",p,&x);
    //We return the memory location of x
    //However, since this is the end of this scope (this function), any variables on the
    //stack from this scope will be deleted, which means by the time we get back to main
    //the variable "x" was deleted, so its spot in memory doesn't mean anything
    return (&x);
}


0 commentaires

0
votes

La fonction g a x déclaré comme variable locale. Cela signifie que x n'est vu / disponible pour fonctionner que là où il est déclaré. Passer le pointeur de x à main est inutile puisque x n'est pas visible pour la fonction main (). C'est toujours une mauvaise pratique de revenir en utilisant le pointeur sauf si nécessaire.


0 commentaires

1
votes

Ce que vous avez observé est un comportement indéfini . Il y a quelque chose qui s'appelle Classe de stockage dans le langage de programmation C. Les variables à l'intérieur de votre fonction int * g (void) ont une classe de stockage automatique . Ils ont une durée de vie et une portée de votre fonction. A chaque fois que vous sortez de votre fonction, l'emplacement alloué à vos variables ( x et * p ) sera détruit.

Donc, cela n'a pas de sens d'utiliser l'adresse des variables avec une classe de stockage automatique en dehors de leur portée, c'est-à-dire en dehors de votre fonction ( int * g (void) ) car le pointeur renvoyé sera un pointeur suspendu.

Vous pouvez utiliser la mémoire dynamique tas pour allouer de l'espace si vous voulez apprendre ou utiliser un emplacement mémoire en dehors de la portée de la fonction.

Vous pouvez également utiliser la variable globale et renvoyer l'adresse mémoire de cette variable globale à partir de votre fonction.

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

int x = 10;

int *g(void)
{
    int *p = &x;
    printf("%p,%p\r\n", p, &x);
    return (&x);
}

int *heap(void)
{
    int *p = malloc(sizeof(int));
    *p = 100;
    printf("%p\r\n", p);
    return p;
}


int main(void)
{
    int *p = g();

    printf("%d\r\n", *p);

    int *p1 = heap();
    printf("%d\r\n", *p1);

    return 0;
}


0 commentaires