IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Retour d'une variable locale


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 22
    Par défaut Retour d'une variable locale
    Bonjour à tous,

    Je m'étonne que le code suivant ne produise pas même un warning et fonctionne comme prévu.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #include <stdio.h>
     
    const char* month(int m)
    {
        const char* month[] =
        {
            "Janvier",
            "Fevrier",
            "Mars",
            "Avril",
            "Mai",
            "Juin",
            "Juillet",
            "Aout",
            "Septembre",
            "Octobre",
            "Novembre",
            "Decembre"
        };
        return month[m-1];
    }
     
    int main()
    {
        printf("%s\n", month(4));
     
        return 0;
    }
    Depuis quand c'est autorisé de renvoyer un pointeur sur une donnée locale ? Oo

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 484
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 484
    Par défaut
    Hello,

    En fait, tu ne renvoies pas le tableau local, mais ce qu'il contient, ce qui est complètement différent. En plus, tu le renvoies par valeur, ce qui est tout-à-fait légal.

    Il se trouve que ce contenu est un pointeur, certes, mais pas vers ta variable locale. Il pointe une chaîne constante, écrite en dur dans ton code : celle que tu as déclarée entre guillemets. En l'occurrence, « Avril ».

    Pour être plus précis, « const char * month[] » ne déclare pas un tableau de caractères qui contiendrait tes chaînes, mais bien un tableau de pointeurs qui, eux, pointent ensuite où ils veulent.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 22
    Par défaut
    Merci de ta réponse,

    Si j'ai bien compris, la fonction month renvoie l'adresse de la chaine "Avril". Mais cette chaine est locale à la fonction.
    Elle est bien allouée sur la pile, comme quand je fais : int a; Non ?
    (edit : même s'il, contrairement a "int a;" elle est anonyme)

    Mais le code suivant marche aussi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    char* foo()
    {
        char* s = "Donuts !";
        return s;
    }
     
    int main()
    {
        char* string = foo();
     
        printf("%s\n", string);
     
        return 0;
    }
    Faut il en conclure que la chaine "Donuts !" n'est pas détruite lorsque la fonction foo termine ? Ce qui me choque, c'est qu'elle soit toujours accessible hors de la fonction ou elle a été déclarée.

    merci d'avance !

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 484
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 484
    Par défaut
    Citation Envoyé par Arwel Voir le message
    Merci de ta réponse, Si j'ai bien compris, la fonction month renvoie l'adresse de la chaine "Avril". Mais cette chaine est locale à la fonction.
    Elle est bien allouée sur la pile, comme quand je fais : int a; Non ?
    Non.
    C'est ton tableau de pointeurs qui l'est. Tes pointeurs reçoivent ensuite des valeurs correspondant aux adresses des chaînes que tu déclares mais qui, elles, sont complètement indépendantes.

    Utilisée seule, l'expression "chaine" est de type const char *. Le compilateur la déclare dans le code et te renvoie son adresse.

    Par contre, si tu avais écrit :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    char chaine [] = "chaine";
    … alors le compilateur aurait bien déclaré un tableau de caractères local, de la taille de la chaîne en question et rempli avec ses caractères.

    Mais le code suivant marche aussi :
    [code]char* foo()
    {
    char* s = "Donuts !";
    return s;
    }
    Même chose :

    • Tu déclares une chaîne « "donuts" ». Elle va quelque part dans ton code, donc en mémoire à lecture seule. L'expression a donc pour valeur un pointeur vers cet emplacement ;
    • Tu déclares un pointeur local s qui reçoit comme valeur l'emplacement de cette chaîne ;
    • Tu retournes la valeur (le contenu) de ce pointeur. Lequel peut disparaître ensuite. L'information est conservée. Cette information est toujours valide hors de la fonction puisque qu'elle fait référence a quelque chose qui s'est toujours trouvé en dehors.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 22
    Par défaut
    Ça y est j'ai enfin compris !

    Merci beaucoup !

  6. #6
    Membre émérite
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Par défaut
    Juste une précision "pratique"...

    Méfie toi Arwel avec la deuxième forme.

    Si tu écris ce qui suit,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #include <stdio.h>
     
    char* foo()
    {
        char* s = "Donuts !";
        return s;
    }
     
    int main()
    {
        char* string = foo();
        string[2] = 'c';
        printf("%s\n", string);	
        printf("%s\n", foo() );	
        return 0;
    }
    Avec gcc, tout simplement, ca crash puisque tu essais de modifier une chaîne constante.
    Avec le compilateur de visual, par un procédé douteux, ça modifie la constante chaîne "Donuts" si bien que tu obtiens à l'affichage :

    Docuts !
    Docuts !

    Du coup, si tu fais pointer des pointeurs vers des constantes chaînes, je te conseille de laisser le "const" qui conduira le compilateur à interdire la modification et forcera la copie.

    (corriger moi si je me plante, je suis surtout ami des std::string )

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débutant] récupération d'une variable local pour l'envoyer a un popup
    Par minogttao dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 25/11/2006, 13h58
  2. [XSLT][XPATH ] Portée d'une variable locale
    Par be_tnt dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 15/11/2006, 15h39
  3. [Tableaux] Retour d'une variable dans une fonction
    Par Will Fou dans le forum Langage
    Réponses: 7
    Dernier message: 02/07/2006, 18h21
  4. Réponses: 4
    Dernier message: 16/02/2006, 10h40
  5. [MFC] Globaliser une variable locale
    Par Philippe320 dans le forum MFC
    Réponses: 3
    Dernier message: 01/12/2005, 20h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo