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 :

[debutant](char **)0 Quel est cette notation ?


Sujet :

C

  1. #1
    Membre averti Avatar de SPACHFR
    Profil pro
    Paaaaaa
    Inscrit en
    Février 2004
    Messages
    557
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Paaaaaa

    Informations forums :
    Inscription : Février 2004
    Messages : 557
    Points : 400
    Points
    400
    Par défaut [debutant](char **)0 Quel est cette notation ?
    Bonjour,

    J'ai un code que j'essai de comprendre, cependant je bloque sur cette notation (char **)0 que je ne comprend pas.

    Je suis allé faire un tour dans les tutorials sur les pointeurs puis sur les listes chainées, mais sans vraiment comprendre cette notation **.
    J'ai bien saisie la notation d'un pointeur, sa déclaration, valorisation ainsi que l'accès en lecture/écriture à l'adresse contenue par un pointeur.
    J'ai retrouvé ** dans le cas d'un exemple de "pile" avec liste chainée mais cette notation n'est pas expliquée.
    Pourriez vous me la décrire ?

    Merci

    Extrait du code :
    La structure
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    struct HWMCA_EVENT_QUALIFIER_S {     
       unsigned long ulEventMask;        
       unsigned long ulType;             
       union {                           
          char szName[256];              
          char cReserved[256];           
       } type;                           
       struct HWMCA_EVENT_QUALIFIER_S *pNext;
    };
    'instructions que je ne comprend pas...
    tQualifier[j] etant un tableau du type de la structure
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    tQualifier[j].ulEventMask = strtoul(argv[i], (char **)0, 0);  
    tQualifier[j].ulType      = strtoul(argv[i+1], (char **)0, 0);
    De plus tQualifier[j].ulEventMask étant de type unsigned long comment peut on mettre 3 arguments dans cet élement : strtoul(argv[i] puis (char **)0 et 0 ?

    Merci
    S'il n'y a pas de solution c'est qu'il n'y a pas de problème.

  2. #2
    Membre expérimenté
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Points : 1 664
    Points
    1 664
    Par défaut
    strtoul() attend un char ** comme deuxieme argument. Ici, on souhaite envoyer NULL. Pourquoi donc mettre (char **) 0 au lieu de NULL ? C'est principalement pour forcer le compilateur a comprendre qu'on se place en contexte pointeur, et que le 0 envoye comme argument est bien un pointeur NULL, pas l'entier zero. Note que dans ton cas, si le prototype de la fonction est present, alors le compilateur sait que l'entier zero represente un pointeur, et le cast n'est pas necessaire. Voir cette reponse dans la 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 : 47
    Localisation : Suisse

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    En gros, il s'agit d'une manière beaucoup moins lisible d'écrire NULL. strtoul() attend en deuxième paramètre un pointeur de type pointeur sur pointeur sur char. Lorsqu'on lui passe une valeur différente de NULL, l'adresse du premier caractère invalide lors de la conversion est placée à l'adresse pointée par ce paramètre. Si on passe NULL, strtoul() considère qu'on utilise pas cette fonctionnalité. Pour en savoir plus sur strtol(), il faut consulter la doc: http://man.developpez.com/man3/strtoul.3.php

    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
    #include <stdlib.h>
     
    int main(void)
    {
        char const *texte = "1977,Thierry";
        int annee;
        char *pend = NULL;
     
        annee = strtoul(texte, &pend, 10);
     
        /* -tc- des le retour de strtoul, annee vaut 1977 et pend vaut l'adresse
            du premier caractere invalide i.e. le caractere ','.
     
            Si on ne desire pas recuperer l'adresse du 1er caractere invalide, on
            simplement NULL a strtoul(): 
            annee = strtoul(texte, NULL, 10); 
        */
     
        return EXIT_SUCCESS;
    }
    (char **) 0 est l'équivalent typé de NULL, mais possède le grand désavantage de casser l'abstraction fournie par NULL.

    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
    Membre averti Avatar de SPACHFR
    Profil pro
    Paaaaaa
    Inscrit en
    Février 2004
    Messages
    557
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Paaaaaa

    Informations forums :
    Inscription : Février 2004
    Messages : 557
    Points : 400
    Points
    400
    Par défaut
    Merci pour vos réponse, j'était tellement perdu par cette notation (char **)0, que j'ai même pas vu que les arguments étaient ceux attendu par le prototype de strtoul().....

    Dernière question, apparement la notation ** désigne un pointeur de pointeur.
    Cela veut t'il dire que :
    **p
    contient l'adresse d'un pointeur ?
    peut on ecrire ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    int a;
    int *p;
    int *pp;
    p=&a
    pp =&p
    printf("a:%d",**pp);
    S'il n'y a pas de solution c'est qu'il n'y a pas de problème.

  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 : 47
    Localisation : Suisse

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par SPACHFR Voir le message
    Merci pour vos réponse, j'était tellement perdu par cette notation (char **)0, que j'ai même pas vu que les arguments étaient ceux attendu par le prototype de strtoul().....

    Dernière question, apparement la notation ** désigne un pointeur de pointeur.
    Cela veut t'il dire que :
    **p
    contient l'adresse d'un pointeur ?
    peut on ecrire ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    int a;
    int *p;
    int *pp;
    p=&a
    pp =&p
    printf("a:%d",**pp);
    Oui.

    EDIT:
    J'était pas très attentif. La façon correcte de faire est:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <stdio.h>
     
    int main(void)
    {
        int a = 100;
        int *p;
        int **pp;
        p=&a;
        pp =&p;
        printf("a:%d",**pp);
     
        return 0;
    }
    où le pointeur pp doit être de type (int **). N'oublie pas d'initialiser a!

    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 Avatar de SPACHFR
    Profil pro
    Paaaaaa
    Inscrit en
    Février 2004
    Messages
    557
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Paaaaaa

    Informations forums :
    Inscription : Février 2004
    Messages : 557
    Points : 400
    Points
    400
    Par défaut
    Un grand merci à tous pour vos répones
    S'il n'y a pas de solution c'est qu'il n'y a pas de problème.

  7. #7
    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 : 47
    Localisation : Suisse

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    J'étais pas très attentif. Ton morceau de code comporte des erreurs. Regarde le poste que j'ai édité ici: http://www.developpez.net/forums/sho...84&postcount=5

    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++

    +

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par SPACHFR Voir le message
    J'ai un code que j'essai de comprendre, cependant je bloque sur cette notation (char **)0 que je ne comprend pas.
    <...>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    tQualifier[j].ulEventMask = strtoul(argv[i], (char **)0, 0);  
    tQualifier[j].ulType      = strtoul(argv[i+1], (char **)0, 0);
    Rien de mystérieux. Dans le contexte 'pointeur' 0 est identique à NULL. Le cast est inutile en C.

    Celui qui a écrit cette horreur ne connait pas le C. Il suffit d'écrire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    tQualifier[j].ulEventMask = strtoul(argv[i], NULL, 0);  
    tQualifier[j].ulType      = strtoul(argv[i+1], NULL, 0);
    Pas de Wi-Fi à la maison : CPL

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par SPACHFR Voir le message
    Dernière question, apparement la notation ** désigne un pointeur de pointeur.
    Cela veut t'il dire que :
    **p
    contient l'adresse d'un pointeur ?
    Oui, ou NULL.
    peut on ecrire ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    int a;
    int *p;
    int *pp;
    p=&a
    pp =&p
    printf("a:%d",**pp);
    Non (il n'est pas inutile de tester son code avant de le poster), mais ceci est correct :
    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
     
    #include <stdio.h>
    int main (void)
    {
       int a = 12;
       int *p;
       int **pp;
     
       p = &a;
       pp = &p;
     
       printf ("a = %d, %d, %d\n", a, *p, **pp);
     
       return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    a = 12, 12, 12
     
    Press ENTER to continue.
    Pas de Wi-Fi à la maison : CPL

  10. #10
    Membre expérimenté
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Points : 1 664
    Points
    1 664
    Par défaut
    Citation Envoyé par Emmanuel Delahaye Voir le message
    Dans le contexte 'pointeur' 0 est identique à NULL. Le cast est inutile en C.
    Pour etre precis, il est inutile si le contexte pointeur est etabli, i.e.
    • il y a un prototype de la fonction en vue (ce qui est requis de toute facon);
    • l'argument n'est pas un argument optionnel d'une fonction variadic, auquel cas le cast est necessaire, puisque le compilateur n'a aucun moyen de determiner le contexte.

  11. #11
    Membre averti Avatar de SPACHFR
    Profil pro
    Paaaaaa
    Inscrit en
    Février 2004
    Messages
    557
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Paaaaaa

    Informations forums :
    Inscription : Février 2004
    Messages : 557
    Points : 400
    Points
    400
    Par défaut
    Merci de ce complément, le petit bout de code que j'ai ajouté, était juste pour être sur d'avoir compris ce qu'était un pointeur de pointeur ainsi que ça notation.
    Mais du coup j'ai encore une question.....sur cette 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
     
    #include <stdio.h>
    int main (void)
    {
       int a = 12;
       int *p;
       int **pp;
     
       p = &a;
       pp = &p;
     
       printf ("a = %d, %d, %d\n", a, *p, **pp);
     
       return 0;
    }
    D'après ce que je crois avoir compris, les pointeurs sont uniquement destinés à contenir une adresse.
    Alors pourquoi exist'il une notation supplémentaire **p afin de déclarer un pointeur de pointeur, puisque un pointeur contient une adresse et que un pointeur de pointeur également ? cela parrait redondant. Je ne vois propablement pas la subtilitée. Quel est l'intêret d'un pointeur de pointeur ?

    Merci
    S'il n'y a pas de solution c'est qu'il n'y a pas de problème.

  12. #12
    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 : 47
    Localisation : Suisse

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Par ce qu'il te faut préciser le type de la variable située à l'adresse stockée dans ton pointeur. Par exemple, lorsque tu écris:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int a = 12;
    int *p = &a;
    Tu informes le compilateur que p pointe sur une variable de type int. Et bien lorsqu'un pointeur contient l'adresse d'un pointeur sur int, c'est la même chose. On écrit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int a = 12;
    int *p = &a;
    int **pp = &p;
    pour lui indiquer que la variable qui se trouve à l'adresse stockée dans pp est de type pointeur sur int. Je ne vois donc rien de redondant là-dedans.

    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++

    +

  13. #13
    Membre averti Avatar de SPACHFR
    Profil pro
    Paaaaaa
    Inscrit en
    Février 2004
    Messages
    557
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Paaaaaa

    Informations forums :
    Inscription : Février 2004
    Messages : 557
    Points : 400
    Points
    400
    Par défaut
    Citation Envoyé par Thierry Chappuis Voir le message

    pour lui (le compilateur) indiquer que la variable qui se trouve à l'adresse stockée dans pp est de type pointeur sur int. Je ne vois donc rien de redondant là-dedans.

    Thierry
    OK, la subtilité était là... c'est au niveau de la compilation que la différence se fait (si j'ai bien compris)

    Merci
    S'il n'y a pas de solution c'est qu'il n'y a pas de problème.

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par SPACHFR Voir le message
    D'après ce que je crois avoir compris, les pointeurs sont uniquement destinés à contenir une adresse.
    Alors pourquoi exist'il une notation supplémentaire **p afin de déclarer un pointeur de pointeur, puisque un pointeur contient une adresse et que un pointeur de pointeur également ? cela parrait redondant. Je ne vois propablement pas la subtilitée. Quel est l'intêret d'un pointeur de pointeur ?
    A ton avis, à quoi sert le 2è paramètre de strtol() ? (A l'origine de la discussion, je le rappelle).
    Pas de Wi-Fi à la maison : CPL

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 05/01/2010, 17h05
  2. Réponses: 5
    Dernier message: 25/03/2006, 00h10
  3. [Débutant(e)] [ClassPath] Quel est son rôle ?
    Par slate dans le forum Général Java
    Réponses: 5
    Dernier message: 06/07/2005, 08h32
  4. [Erreur] Quel est cette erreur?
    Par netah25 dans le forum C++Builder
    Réponses: 3
    Dernier message: 11/08/2004, 10h16

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