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 :

Probléme de compréhension avec les pointeurs


Sujet :

C

Vue hybride

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 13
    Par défaut Probléme de compréhension avec les pointeurs
    Bonjour,

    j'ai trouve sur le site le code d'une fonction qui permet de réaliser l'échange de pointeurs mais je n'arrive pas à comprendre son fonctionnement. En effet, je me perds dans la signification des pointeurs. J'ai du mal à comprendre la signification du pointeur générique void * et encore plus de *(void **)d1. Pourquoi avoir placé deux opérateurs de déférencence aprés le void?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void swap( void * d1 , void * d2 )
    {
    	void * tmp;
    	tmp = *(void **)d1;
    	*(void **)d1 = *(void **)d2;
    	*(void **)d2 = tmp;
    }
    Merci beaucoup pour votre aide et pour vos réponses.

  2. #2
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Salut,

    void * est un pointeur générique. Il permet de stocker l'adresse d'une variable sans s'intéresser au type de la variable en question.

    Il est interdit de déréférencer un pointeur void *. La ligne suivante:
    te permet de stocker la valeur située à l'adresse pointée par d1 en tromper le compilateur. On lui dit: "Je veux traiter d1 comme un pointeur-sur-pointeur-sur void", puis on déréférence d1 pour accéder à la valeur et la stocker dans tmp.

    Personnelement, je ne trouve cette façon de faire pas propre du tout, et je la déconseille. En plus, si l'auteur a voulu une fonction swap générique, c'est raté, car cela ne fonctionne qui si le type de la variable pointée a la même taille qu'un pointeur: dès lors, mieux vaut faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    swap_int(int *d1, int *d2)
    {
        int tmp;
        tmp = *d1;
        *d1 = *d2;
        *d2 = tmp;
    }
    ou

    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
    void swap(void *d1, void *d2, char const *type)
    {
        if (!(strcmp(type, "int"))
        {
            int tmp;
            tmp = *(int*)d1;
            *(int*)d1 = *(int*)d2;
            *(int*)d2 = tmp;
        }
        else if (!strcmp(type, "double")
        {
            /* ... */
        } 
        /* ... */
    }
    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  3. #3
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Ce tutoriel http://rperrot.developpez.com/articles/c/genericite/ propose une solution générique intéressante:
    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
    int swap_generic(void *const a, void *const b, size_t size)
    {
       void *const temp = malloc(size);
     
       if ( temp == NULL )
         return EXIT_FAILURE;
     
       memcpy(temp, a, size);
       memcpy(a, b, size);
       memcpy(b, temp, size);
     
       free(temp);
     
      return EXIT_SUCCESS;
    }
    Voici un exemple d'utilisation:

    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
    int main(void)
    {
    	int i1 = 10;
    	int i2 = 100;
    	double d1 = 10.562;
    	double d2 = 100.9978;
     
    	/* On échange les deux valeurs de type int*/
    	printf("AVANT: i1 = %d\ti2 = %d\n", i1, i2);
    	swap_generic(&i1, &i2, sizeof i1);
    	printf("APRES: i1 = %d\ti2 = %d\n", i1, i2);
     
    	/* On échange les deux valeurs de type double*/
    	printf("AVANT: d1 = %f\td2 = %f\n", d1, d2);
    	swap_generic(&d1, &d2, sizeof d1);
    	printf("APRES: d1 = %f\td2 = %f\n", d1, d2);
     
    	return EXIT_SUCCESS;
    }
    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  4. #4
    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 mujigka
    En plus, si l'auteur a voulu une fonction swap générique<...>
    Ben non:
    Citation Envoyé par P.O.
    fonction qui permet de réaliser l'échange de pointeurs

  5. #5
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Ben non:
    Citation:
    P.O. a écrit :
    fonction qui permet de réaliser l'échange de pointeurs
    Autant pour moi! Dans le cas de l'échange de pointeur, il n'y a aucun soucis avec le code présenté. C'est moi qui ai tout compris de travers (enfin presque tout).

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 13
    Par défaut
    Tout d'abord merci pour vos réponses. Elles m'ont éclairé sur quelques points.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void swap( void * d1 , void * d2 )
    {
    	void * tmp;
    	tmp = *(void **)d1;
    	*(void **)d1 = *(void **)d2;
    	*(void **)d2 = tmp;
    }
    Je ne comprend pas tres bien ce que veut dire mujigka par :

    Je veux traiter d1 comme un pointeur-sur-pointeur-sur void, puis on déréférence d1 pour accéder à la valeur et la stocker dans tmp.
    En effet, pour moi l'expression void *d1 est equivalente à (void **)d1 cad d1 est un pointeur sur un "type void".

    D

  7. #7
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    void* est un type de pointeur générique, on peut mettre n'importe quoi dedans.
    Ainsi, lors de l'appel:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
       char const *pa = "hello";
       char const *pb = "world";
     
       pswap (&pa, &pb);
    On passe des char const * * implicitement transtypés en void*.

    Une fois dans la fonction, on a besoin du niveau d'indirection qu'on avait supprimé dans le void *, ainsi on fait ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void pswap (void *p1, void *p2)
    {
       void **pp1 = p1; /* adresses des pointeurs */
       void **pp2 = p2;
    Ainsi, pp1 et pp2 sont bien des pointeurs vers pointeurs, comme le sont les paramètres réels.
    On peut alors utiliser pp1 et pp2 pour faire l'échange des pointeurs.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par *air*
    Je ne comprend pas tres bien ce que veut dire mujigka par :
    Citation Envoyé par mujigka
    Je veux traiter d1 comme un pointeur-sur-pointeur-sur void, puis on déréférence d1 pour accéder à la valeur et la stocker dans tmp.
    En effet, pour moi l'expression void *d1 est equivalente à (void **)d1 cad d1 est un pointeur sur un "type void".
    Une grande partie de ce que j'ai dit est dû à ma mauvaise compréhension de ta question (je n'avais pas compris que tu désirais faire un swap de pointeurs). Ainsi, dans le cadre de l'échanche de pointeurs, la fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void pswap( void * pd1 , void * pd2 )
    {
    	void * p_tmp;
    	p_tmp = *(void **)pd1;
    	*(void **)pd1 = *(void **)pd2;
    	*(void **)pd2 = p_tmp;
    }
    fait bien le job qu'elle est sensée faire.

    Ici, l'instruction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void *p_tmp = *(void**)pd1;
    est équivalente aux instructions:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    void **ppd1 = (void**)pd1;
    void *p_tmp = *ppd1;
    Il faut comprendre ici que le type void* n'est pas équivalent à void**, car tu ne peux pas écrire *pd1 (i.e. tu peux pas déréférencer pd1, car tu ne connais pas le type de la valeur contenue à cette adresse) mais tu peux écrire *ppd1 (i.e. tu peux déréférencer ppd1, car tu sais que la valeur contenue à cette adresse est un pointeur).

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  9. #9
    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 *air*
    j'ai trouve sur le site le code d'une fonction qui permet de réaliser l'échange de pointeurs mais je n'arrive pas à comprendre son fonctionnement.
    Normal, c'est codé avec les pieds... Il est extrêmement facile d'écrire du code illisible en C. Il est beaucoup plus utile d'écrire du code lisible...
    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
     
    void pswap (void *p1, void *p2)
    {
       void **pp1 = p1; /* adresses des pointeurs */
       void **pp2 = p2;
       void *ptmp = *pp1; /* echange (temporaire) */
       *pp1 = *pp2;
       *pp2 = ptmp;
    }
     
    #include <stdio.h>
     
    int main (void)
    {
       char const *pa = "hello";
       char const *pb = "world";
     
       printf ("%s %s\n", pa, pb);
       pswap (&pa, &pb);
       printf ("%s %s\n", pa, pb);
       return 0;
    }

Discussions similaires

  1. Réponses: 10
    Dernier message: 26/11/2012, 10h45
  2. Problème de compréhension avec les DIV
    Par akaii dans le forum Mise en page CSS
    Réponses: 3
    Dernier message: 25/02/2010, 01h32
  3. probléme avec les pointeurs
    Par killer_instinct dans le forum C++
    Réponses: 6
    Dernier message: 11/12/2006, 11h37
  4. Réponses: 5
    Dernier message: 18/10/2006, 16h20
  5. [TTreeView] Problème avec les pointeurs d'objet
    Par BlackWood dans le forum Composants VCL
    Réponses: 2
    Dernier message: 02/07/2004, 14h31

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