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 :

pointeurs ... encore !


Sujet :

C

  1. #1
    Membre averti
    Inscrit en
    Janvier 2004
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Janvier 2004
    Messages : 25
    Par défaut pointeurs ... encore !
    Bonjour,

    J'essaie de passer des paramètres à mes fonctions par référence, donc en utilisant des pointeurs ..... sauf que ca ne fonctionne pas comme je le souhaiterait !

    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
    29
    30
    31
     
    void resolv(char *hote)
    {
    struct hostent *   hostent  = NULL;
    struct in_addr adresse_ip;
    if (hote != NULL)
      {  if ((hostent = gethostbyname (hote)) == NULL)  
          {  if (!inet_aton(hote,&adresse_ip))			
    	{usage();	
    	}
          }
         else  {	hote = inet_ntoa(*(struct in_addr*) hostent->h_addr);
    		}
      }
    } 
     
    void create_conninfo(char *conninfo, char *dbname, char *user, char *password, char *hostaddr)
    {      strcat(conninfo,"dbname = ");
    	strcat(conninfo,dbname);
    	strcat(conninfo," user = ");
    	strcat(conninfo,user);
    	......	
    }
     
    main(int argc, char **argv)
    {
    char *conninfo, *hote, *user;
     
    resolv(hote); 
    if ((conninfo = (char *) malloc (strlen(dbname) + strlen(user) + strlen(password) + strlen(hote) + 256)) != NULL ) 	create_conninfo(conninfo, dbname, user, password, hote);
    }

    Visiblement, create_conninfo modifie bien la chaine pointée par conninfo, par contre, resolv ne modifie pas la valeur de hote .... ?

    J'ai vraiment du mal avec les pointeurs, si vous pouviez m'aider a comprendre ce qui ne va pas dans ce cas là ?

    Merci !

    Jeremy

  2. #2
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2005
    Messages
    357
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2005
    Messages : 357
    Par défaut
    Ce serait bien de savoir ce que hote contient. montre-nous comment tu garnis hote avant d'appeler resolv.

    Et puis aussi essaie d'écrire ton code proprement, il m'a fallu du temps pour le comprendre : choisis une règle d'indentation parce que là tu mélange plusieurs styles et ça rend ton code illisible, j'ai du le remettre en page pour le lire :

    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
    29
    30
    31
    void resolv(char *hote){
      struct hostent *   hostent  = NULL;
      struct in_addr adresse_ip;
      if (hote != NULL)  {
        if ((hostent = gethostbyname (hote)) == NULL) {  
          if (!inet_aton(hote,&adresse_ip)) {
            usage();   
          }
        }
        else  {
          hote = inet_ntoa(*(struct in_addr*) hostent->h_addr);
        }
      }
    }
     
    void create_conninfo(char *conninfo, char *dbname, char *user, char *password, char *hostaddr){
      strcat(conninfo,"dbname = ");
      strcat(conninfo,dbname);
      strcat(conninfo," user = ");
      strcat(conninfo,user);
      ......   
    }
     
    main(int argc, char **argv) {
     
      char *conninfo, *hote, *user;
     
      resolv(hote);
      if ((conninfo = (char *) malloc (strlen(dbname) + strlen(user) + strlen(password) + strlen(hote) + 256)) != NULL )
        create_conninfo(conninfo, dbname, user, password, hote);
    }

  3. #3
    Membre averti
    Inscrit en
    Janvier 2004
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Janvier 2004
    Messages : 25
    Par défaut
    Merci pour la réponse rapide

    Désolé pour l'indentation ... j'ai un peu du mal a savoir comment faire : 1 tab a chaque fois, l'accolade fermant a la fin de la ligne, ou au début ... Bref, mes excuses pour ca !

    hote a l'origine contient l'argument passé en paramètre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    while ((option = getopt(argc,argv,"a:b:u:p:v:h")) != -1) {
    		switch(option) {
    		          case 'a':
    		          if ((hote = (char *) malloc (strlen (optarg) +1 )) != NULL)
    		          strcpy (hote, optarg);
    		          else perror("malloc hote");
    		          break;
                    }
    }
    ensuite j'appelle resolv(hote);

    Jeremy

  4. #4
    Membre éprouvé Avatar de kaisse
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    100
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 100
    Par défaut
    Le "passage par référence" est un abus de langage en C. On le dit quand on passe un pointeur sur une valeur/structure au lieu de passer la valeur/structure elle-même. Mais ce pointeur, lui, est bien passé par valeur: c'est à dire que c'est une copie du pointeur qu'on obtient. En général, on s'en fout, puisque c'est ce qui est pointé par le pointeur qui nous interresse, et donc, seule sa valeur nous interresse. Seulement ici, tu essaies de modifier le pointeur lui-même:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    hote = inet_ntoa(*(struct in_addr*) hostent->h_addr);
    Or le pointeur est modifié dans le corps de la fonction, mais ce n'est pas celui que tu as tranmis en argument, c'en est une copie. Donc c'est le pointeur lui-même que tu dois passez "par référence", c'est à dire passer un pointeur sur pointeur.

    Typiquement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    void resolv (char **host)
    {
       ....
       *hote = .....;
    }
     
    ....
     
    int main (void)
    {
         char *hote;
         resolv (&hote);
    }

  5. #5
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut Re: pointeurs ... encore !
    Citation Envoyé par jems
    Bonjour,

    J'essaie de passer des paramètres à mes fonctions par référence,
    Meuh! Pas de 'par référence' en C. 'par valeur' uniquement.

    Ton code n'est pas compilable. Il semble que tu passes un pointeur indéterminé à une fonction. Le comportement est indéfini.

  6. #6
    Membre expérimenté Avatar de fred777888999
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    250
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 250
    Par défaut
    Citation Envoyé par kaisse
    Le "passage par référence" est un abus de langage en C. On le dit quand on passe un pointeur sur une valeur/structure au lieu de passer la valeur/structure elle-même. Mais ce pointeur, lui, est bien passé par valeur: c'est à dire que c'est une copie du pointeur qu'on obtient. En général, on s'en fout, puisque c'est ce qui est pointé par le pointeur qui nous interresse, et donc, seule sa valeur nous interresse. Seulement ici, tu essaies de modifier le pointeur lui-même:
    En resumé et pour faire plus simple, tu dois passer, a ta fonction, un pointeur sur ce que tu veux modifier. Si tu veux modifier un pointeur, il faut passer un pointeur sur ce dernier donc un pointeur de pointeur...

  7. #7
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2005
    Messages
    357
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2005
    Messages : 357
    Par défaut
    Elle retourne quoi, la fonction inet_ntoa() comme type ?

  8. #8
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par fred777888999
    En resumé et pour faire plus simple, tu dois passer, a ta fonction, un pointeur sur ce que tu veux modifier. Si tu veux modifier un pointeur, il faut passer un pointeur sur ce dernier donc un pointeur de pointeur...
    Pas un pointeur. Une adresse...

    "tu dois passer, à ta fonction, l'adresse de ce que tu veux modifier." et là, tout deviens simple. Il faut un paramètre de type pointeur sur le bon type. Secouer son neurone, et c'est réglé.

  9. #9
    Membre expérimenté Avatar de fred777888999
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    250
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 250
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Pas un pointeur. Une adresse...
    Comme toute variable que tu passes a une fonction c'est effectivement mieux si elle est initialisée... Je ne vois pas vraiment l'interet de le preciser Si tu passes un indefini a une fonction ca sert a rien mais c'est pas specifique aux pointeurs...
    à ma connaissance :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char b;
    toto (&b)
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    char b;
    char *a;
    *a = &b;
    toto(a);
    sont complétement equivalents du point de vue du resultat... et avec un compilo pas trop merdique avec un optimiseur pas trop nul (eviter les kro$ofteries) a meme de grandes chances de generer le meme executable....

  10. #10
    Membre averti
    Inscrit en
    Janvier 2004
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Janvier 2004
    Messages : 25
    Par défaut
    Merci a tous pour vos réponses.

    J'ai essayé de "dessiner" ce que j'avais compris : https://jems0.dyndns.org/pointeurs.png

    Et vu que je passe la valeur du pointeur au pointeur dans la fonction, je ne comprends pas pourquoi il faut utiliser un super pointeur. Mon raisonnement est faux, mais je ne trouve pas où, c'est pourquoi j'ai essayé de représenter les choses comme je les voie.

    explication du schéma (donc faux, puisque c'est ce que je comprends) :
    hote (dans main) contient l'adresse d'une zone qui contient des caractères.
    quand j'appelle resolv(hote), je transmet a un deuxieme pointeurs (on l'appelle hote2 pour éviter les confusions) la valeur de hote.
    Donc hote2, pointeur de son état, contient l'adresse de la même zone que celle pointée par hote. Si je modifie hote2, je modifie donc la même zone mémoire que celle pointée par hote.
    Quand je reviens dans mon main, je retrouve ma zone pointée par hote (modifiée par hote2).

    Dans mon raisonnement, j'ai donc 2 pointeurs différents qui pointent vers la même zone, et donc quand l'un modifie la zone pointée, l'autre "voit" les modifications.


    Il y a quelque chose que j'ai raté, mais quoi ?

  11. #11
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Citation Envoyé par jems
    J'ai essayé de "dessiner" ce que j'avais compris : https://jems0.dyndns.org/pointeurs.png
    Impossible d'afficher la page
    Si c'est ce que tu as compri des pointeurs...

  12. #12
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par jems
    Il y a quelque chose que j'ai raté, mais quoi ?
    Explication simple.

    J'ai un int
    j'ai une fonction qui doit mettre 123 dans l'int. Comment je fais ?

    Méthode naive:
    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
     
    #include <stdlib.h>
    #include <stdio.h>
     
    static void f (int y)
    {
       y = 123;
    }
     
    int main (void)
    {
       int x;
     
       f (x);
     
       printf ("x=%d\n", x);
     
       /* Dev-C++ trick ... */
       system ("pause");
       return 0;
    }
    Résultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    x=5767168
    Appuyez sur une touche pour continuer . . .
    Y'a un bug. Pourquoi ?

    Si tu arrives à l'expliquer, tu sais résoudre ton autre problème.

    Le sage a dit :

    "Avant de faire des choses compliquées, fait des choses simples".

  13. #13
    Membre averti
    Inscrit en
    Janvier 2004
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Janvier 2004
    Messages : 25
    Par défaut
    Désolé pour l'image inaccessible ... c'est réparé maintenant.

    Pour Emmanuel :

    Oui, je comprends bien que x est interne a la fonction, est que du coup il n'est jamais initialisé dans le main. Ce qui explique le printf.

    Ce que je ne comprends pas, c'est le pointeur. Un pointeur "pointe" sur quelque chose. pour moi si je copie la valeur d'un pointeur dans un autre pointeur, j'obtiens 1 deuxième pointeur sur la même zone mémoire, donc contenant les mêmes données. Du coup quand je travaille avec l'un ou avec l'autre, je travaille sur la même donnée.

    La je me rends compte d'un truc : en fait le pointeur ne contient pas l'adresse de la première case mémoire, mais il EST la première case mémoire peut-être ? C'est pour ca qu'il faut en passer l'adresse a la focntion ? ( resolv(&hote) ) et non pas la valeur (premier caractère du nom d'hote en l'occurence ?)

    Ce qui ne semble pas être le cas ???

  14. #14
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Citation Envoyé par jems
    Ce que je ne comprends pas, c'est le pointeur. Un pointeur "pointe" sur quelque chose. pour moi si je copie la valeur d'un pointeur dans un autre pointeur, j'obtiens 1 deuxième pointeur sur la même zone mémoire, donc contenant les mêmes données. Du coup quand je travaille avec l'un ou avec l'autre, je travaille sur la même donnée.
    oui

    Citation Envoyé par jems
    La je me rends compte d'un truc : en fait le pointeur ne contient pas l'adresse de la première case mémoire, mais il EST la première case mémoire peut-être ? C'est pour ca qu'il faut en passer l'adresse a la focntion ? ( resolv(&hote) ) et non pas la valeur (premier caractère du nom d'hote en l'occurence ?)
    Bah non
    Quelques explications: http://chgi.developpez.com/pointeur/

  15. #15
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par jems
    Oui, je comprends bien que x est interne a la fonction, est que du coup il n'est jamais initialisé dans le main. Ce qui explique le printf.

    Ce que je ne comprends pas, c'est le pointeur.
    C'est exactement pareil :
    Code identique (sauf que j'initialise le pointeur pour que ce soit plus parlant)
    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
     
    #include <stdlib.h>
    #include <stdio.h>
     
    static void f (int *py)
    {
       py = malloc(sizeof (int));
    }
     
    int main (void)
    {
       int *p = NULL;
     
       f (p);
     
       printf ("p=%p\n", (void*)p);
     
       /* Dev-C++ trick ... */
       system ("pause");
       return 0;
    }
    ce qui donne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    p=00000000
    Appuyez sur une touche pour continuer . . .
    sauf que c'est un peu moins parlant, c'est vrai, car on ne sait pas trop à quelle valeur de pointeur s'attendre. En tout cas, pas à 0

    Explication détaillée:
    Un pointeur est défini. Sa valeur est définie à 0 (NULL).
    sa valeur (NULL) est passée à la fonction. Pourquoi pas...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    static void f (int *py)
    {
    Une copie de cette valeur est recueillie dans le paramètre py. Cette valeur est évidemment NULL.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       py = malloc(sizeof (int));
    Cette valeur est modifiée avec l'adresse d'un bloc alloué. Ok.

    La valeur originale de px a-t-elle été modifiée ? Non.

    Donc, opération blanche.

    C'est plus clair ?

  16. #16
    Membre averti
    Inscrit en
    Janvier 2004
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Janvier 2004
    Messages : 25
    Par défaut
    sa valeur (NULL) est passée à la fonction. Pourquoi pas...
    Code:

    static void f (int *py)
    {

    Une copie de cette valeur est recueillie dans le paramètre py. Cette valeur est évidemment NULL.
    Code:
    py = malloc(sizeof (int));

    Cette valeur est modifiée avec l'adresse d'un bloc alloué. Ok.

    La valeur originale de px a-t-elle été modifiée ? Non.

    Donc, opération blanche.

    C'est plus clair ?

    NULL est passé a py : ok.
    on réalloue py dans la fonction, ca n'est pas retransmis a p : ok.

    Ce qui me chagrine, c'est quand on alloue avant d'appeler la fonction.

    Si p est alloué avant d'appeler : il contient une adresse (mettons l'adresse 3). on copie donc cette valeur dans py (donc py contient 3, donc *py est la valeur contenu a l'adresse 3 ?

    si je modifie la valeur contenue a l'adresse 3, quand je sors de ma fonction, la valeur pointée par p a changée aussi, non ?

    Je fais des essais de codes, ca va rentrer a force !

    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
    29
    #include <stdio.h>
    #include <stdlib.h>
     
    void modif(char ** e)
    { 
       printf("e = %ld %ld %s \n",&e, e, e);
       strcpy(*e,"une chaine");
       return;
    }
     
    int main (void)
    {	
       char *j;
       char  i[15]="des chaines";
       j = i;
       printf("i = %ld %ld %s \n",&i, i, i);
       printf("j = %ld %ld %s \n",&j, j, j);
       modif(&j);
     
       printf("i = %d %d %s\n",&i, i, i);
       return 0;
    }
     
    [resultat]
    i = -1073743280 -1073743280 des chaines
    j = -1073743252 -1073743280 des chaines
    e = -1073743296 -1073743252 Púÿ¿
    i = -1073743280 -1073743280 une chaine
    [/resultat]
    Pas d'erreur de compilation, pourtant e ne pointe pas vers la bonne chaine.

    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
    29
    30
    31
     
    #include <stdio.h>
    #include <stdlib.h>
     
    void modif(char * e)
    { 
       printf("e = %ld %ld %s \n",&e, e, e);
       strcpy(e,"une chaine");
       return;
    }
     
    int main (void)
    {	
       char *j;
       char  i[15]="des chaines";
       j = i;
       printf("i = %ld %ld %s \n",&i, i, i);
       printf("j = %ld %ld %s \n",&j, j, j);
       modif(j);
     
       printf("i = %d %d %s\n",&i, i, i);
       return 0;
    }
     
    [resultat]
    i = -1073743280 -1073743280 des chaines
    j = -1073743252 -1073743280 des chaines
    e = -1073743296 -1073743280 des chaines
    i = -1073743280 -1073743280 une chaine
     
    [/resultat]
    Et la sans super pointeur ca fonctionne comme je le souhaite ....

    C'est pourtant pas si compliqué que ca les pointeurs ! (la je m'enerve contre moi !)

    Bon, tant que c'est pas rentré, je continue !

    Merci pour votre aide en tout cas, et pour les liens !

  17. #17
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par jems
    sa valeur (NULL) est passée à la fonction. Pourquoi pas...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    static void f (int *py)
    {
    Une copie de cette valeur est recueillie dans le paramètre py. Cette valeur est évidemment NULL.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       py = malloc(sizeof (int));
    Cette valeur est modifiée avec l'adresse d'un bloc alloué. Ok.

    La valeur originale de px a-t-elle été modifiée ? Non.

    Donc, opération blanche.

    C'est plus clair ?
    NULL est passé a py : ok.
    on réalloue py dans la fonction, ca n'est pas retransmis a p : ok.
    ??? On a rien réalloué du tout. On a modifié la valeur du pointeur py. Comme je l'explique dans mon article :

    http://emmanuel-delahaye.developpez.....htm#pointeurs

    un pointeur est une variable comme une autre, sauf que sa valeur est une adresse ou NULL.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       py = malloc(sizeof (int));
    ne signifie ni 'allouer un pointeur' ni 'réallouer un pointeur', mais 'allouer un int et ranger son adresse dans le pointeur py'.
    Ce qui me chagrine, c'est quand on alloue avant d'appeler la fonction.

    Si p est alloué avant d'appeler : il contient une adresse (mettons l'adresse 3). on copie donc cette valeur dans py (donc py contient 3, donc *py est la valeur contenu a l'adresse 3 ?
    Oui.
    si je modifie la valeur contenue a l'adresse 3, quand je sors de ma fonction, la valeur pointée par p a changée aussi, non ?
    Oui.
    Je fais des essais de codes, ca va rentrer a force !
    Tu fais des choses trop compliquées. Tu n'as pas suivi le conseil du vieux sage.

    Continuons pas à pas. Je repart de mon premier exemple avec x = 123 et f() qui ne modifiais pas x. La compréhension de la correction est fondamentale, car elle explique tout le reste.
    Je recite l'exemple :
    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
     
    #include <stdlib.h>
    #include <stdio.h>
     
    static void f (int y)
    {
       y = 123;
    }
     
    int main (void)
    {
       int x;
     
       f (x);
     
       printf ("x=%d\n", x);
     
       /* Dev-C++ trick ... */
       system ("pause");
       return 0;
    }
    Pourquoi la fonction f() ne modifie pas 'x', tout simplement par ce que les passages de paramètres en C étant faits exclusivement par valeur, c'est une copie de x qui est reçue dans f(). Cette copie est dans y. On peut modifier y tant qu'on veut, x ne changera pas.

    Comment faire pour que f() puisse modifier x ? L'astuce est de passer à la fonction, non pas la valeur de la variable qui n'interesse personne, mais l'adresse de cette variable, qui permet, via un pointeur adéquante (du bon type) d'accéder à la variable originelle en lecture et surtout en écriture grâce à l'opérateur d'indirection '*'.

    Ce paragraphe est l'essence même du C. Il doit être lu, compris, assimilé et retenu.

    Il explique pourquoi on doit modifier la fonction de façon à ce qu'elle puisse recevoir l'adresse de la variable
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    static void f (int *py)
    et qu'elle puisse ecrire dedans:
    (on verra plus tard qu'il faut être plus prudent que ça...)

    et donc modifier l'appel de façon à passer l'adresse de la variable:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
       int x;
     
       f (&x);
    Ce qui donne, avec une précaution d'usage avant d'utiliser (déréférencer) le pointeur :
    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
     
    #include <stdlib.h>
    #include <stdio.h>
     
    static void f (int *py)
    {
       if (py != NULL)
       {
          *py = 123;
       }
    }
     
    int main (void)
    {
       int x;
     
       f (&x);
     
       printf ("x=%d\n", x);
     
       /* Dev-C++ trick ... */
       system ("pause");
       return 0;
    }
    ce qui donne

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    x=123
    Appuyez sur une touche pour continuer . . .
    Une fois que tu as compris ce code, et en suivant la même démarche, tu résous le problème de la fonction qui met à jour un pointeur.

  18. #18
    Membre averti
    Inscrit en
    Janvier 2004
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Janvier 2004
    Messages : 25
    Par défaut
    Eh bien merci beaucoup pour les explications !

    J'ai (presque) réussi a faire mon premier prog en C !

    Maintenant j'ai un problème de comportement bizarre de malloc, mais ca va faire l'objet d'un autre topic.

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

Discussions similaires

  1. Les pointeurs encore et toujours
    Par Arkenis dans le forum Débuter
    Réponses: 6
    Dernier message: 17/05/2012, 23h04
  2. Réponses: 5
    Dernier message: 26/10/2008, 14h05
  3. Encore une histoire de pointeur
    Par Supersami2000 dans le forum C
    Réponses: 5
    Dernier message: 11/07/2008, 13h42
  4. Problème de pointeur (encore un)
    Par Arry_C dans le forum C
    Réponses: 16
    Dernier message: 30/05/2006, 19h47
  5. Encore Pointeur
    Par Naruto_kun dans le forum C
    Réponses: 10
    Dernier message: 14/12/2005, 14h10

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