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 :

les pointeur * et &


Sujet :

C++

  1. #1
    Membre confirmé
    Inscrit en
    Août 2002
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 157
    Par défaut les pointeur * et &
    binjour,
    quelqu'un peut m'expliquer pourquoi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int x=10,*ptr;
    ptr=&x;
    cout<<*(&ptr)<<endl;
    et renvoie la meme adresse
    Merci èa vous

  2. #2
    Membre expérimenté
    Profil pro
    Étudiant
    Inscrit en
    Avril 2007
    Messages
    181
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2007
    Messages : 181
    Par défaut
    Salut,
    &ptr donne l'adresse du pointeur (généralement, on s'en moque...), et l'opérateur * donne la valeur pointée par cette adresse, et donne donc... ptr !

    *ptr déréférence le pointeur (c'est à dire : donne la valeur pointée), et tu récupères ensuite l'adresse de cette valeur, tu retombes à nouveau sur ptr.

    Dans les deux cas tu affiches la valeur de ptr, qui est l'adresse de x. ptr a lui même une adresse, qui n'a rien à voir avec sa valeur.
    Ces quatre expressions donnent toutes la même valeur :
    • *(&ptr)
    • &(*ptr)
    • ptr
    • &x

  3. #3
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    J'ai le même code asm pour les 4 formes. Cependant, j'aurais (peut être à tort) toujours une angoisse à écrire &(*ptr) pour ptr non initialisé alors que pour les autres formes, je n'y verrais pas d'inconvénient.

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Écrire &*ptr est bien sûr un comportement indéfini si ptr ne pointe pas vers un objet valide.

  5. #5
    Membre confirmé
    Inscrit en
    Août 2002
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 157
    Par défaut
    Merci beaucoup pour vos reponses.
    en effet vu de cette maniere tout est claire. cependant un question me vientà l'espris en lisant les reponses quand tu as dis que * dereference ptr. je comprends ca tres bien
    par contre dans la declaration
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int ** ptr;*ptr = new int[10]
    qu'estce qui fais qu'on peux declarer un tableau comme de cette maniere.

    le premier * est pour definir un tableau de une dimension qui contient des pointer de type int c'est ca
    ce que j'essai de comprends c'est l'emploi de * en general s'il ya un article un tuto qui explique ca bien ca sera bievenue!
    Merci

  6. #6
    Membre expérimenté
    Profil pro
    Étudiant
    Inscrit en
    Avril 2007
    Messages
    181
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2007
    Messages : 181
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int ** ptr;
    *ptr = new int[10];
    Ce code est faux et provoque un comportement indéfini.

    Citation Envoyé par mahboub
    le premier * est pour definir un tableau de une dimension qui contient des pointer de type int c'est ca
    Évite de parler de dimensions et de tableaux, car int** ptr n'a rien d'un tableau. ptr est ici un pointeur sur pointeur sur int.
    Si tu veux un tableau de pointeurs sur int, tu dois faire comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int** ptr = NULL;
    ptr = new int* [10];
    L'instruction "new TYPE" retourne l'adresse d'une zone mémoire de type pointeur sur TYPE, donc new int* retourne bien une adresse de type int**.
    Voyons maintenant pourquoi ton code était faux : *ptr = new int[10];
    *ptr déréférence le pointeur, ce qui donne un int*.
    Mais qu'en est-il de sa valeur ? Impossible à prédire car le pointeur n'est pas initialisé.
    Lorsque tu déclares un pointeur, tu dois toujours lui mettre une valeur (soit l'adresse de l'élément pointé, soit NULL, ça dépend du contexte d'utilisation).
    new int[10] retourne l'adresse d'une zone mémoire allouée dynamiquement (une zone de 10 int), et tu écris cette adresse à *ptr. Un pointeur non initialisé contient bien une adresse, c'est à dire ce qu'il y avait avant à cet emplacement mémoire. Et il y a de forte chance que cette adresse n'appartienne pas à ton programme, tu tentes donc d'écrire dans une zone qui ne t'appartient pas (c'est une violation mémoire, l'OS tue ton programme et tu obtiens une erreur de segmentation).

  7. #7
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 454
    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 454
    Par défaut
    Citation Envoyé par mahboub Voir le message
    qu'estce qui fais qu'on peux declarer un tableau comme de cette maniere.

    le premier * est pour definir un tableau de une dimension qui contient des pointer de type int c'est ca
    ce que j'essai de comprends c'est l'emploi de * en general s'il ya un article un tuto qui explique ca bien ca sera bievenue!
    « * » désigne un pointeur. Donc « int * » désigne un pointeur sur un entier, soit une variable qui contient l'adresse en mémoire d'un entier quelquonque. Or, si un pointeur est en soi une variable, il a également une adresse, et il peut donc être référencé.

    « int ** » est donc un pointeur sur un pointeur sur un entier ;
    « int *** » est un pointeur sur un pointeur sur un pointeur sur un entier;
    etc.

    Ce qui distingue un pointeur d'un autre type de données, c'est que l'adresse qu'il contient est a priori celle de quelque chose d'autre. Cette adresse peut donc être exploitée en tant que telle (affichage, comparaison, ...) ou bien suivie pour atteindre ce qu'il pointe (indirection). Tant que l'on tombe sur un pointeur, on peut continuer. Tous les autres types sont terminaux.

    Maintenant, les tableaux : en C et C++, la mémoire n'est pas particulièrement structurée quand tu déclares un tableau. La principale chose que fait le langage est réserver suffisamment de mémoire contigüe pour y stocker tous tes éléments. Dès lors, la seule chose que tu as besoin de connaître pour exploiter ton tableau est l'endroit où il commence. Après, tu n'as qu'à multiplier les numéro du rang et taille de ton élément pour connaître le décalage (offset) par rapport au début (adresse de base) et le retrouver.

    C'est pourquoi, lorsque tu déclares un tableau en C ou C++, il y a systématiquement un pointeur créé avec. Celui-là même qui te donne son emplacement en mémoire. Ainsi un « char[10] » occupera 14 octets (10 + 4). Un « char [] » ne déclarera donc le pointeur et sera donc équivalent à « char * ». D'ailleurs, tu peux utiliser comme tableau n'importe quel pointeur même s'il n'a pas été déclaré à l'avance avec des crochets. Tu peux aussi utiliser l'arithmétique des pointeurs : « (ptr + 1) » ne te donnera pas forcément l'adresse du prochain octet en mémoire, mais l'emplacement du prochain élément (une sorte de « (ptr + 1*sizeof(type) »).

    Enfin, comme l'a signalé Haze, ton code avec **ptr est incorrect ici ... parce que ptr n'est pas initialisé. Dans un autre contexte, il aurait été parfaitement valide et aurait représenté ... un tableau de tableaux !

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par loufoque Voir le message
    Écrire &*ptr est bien sûr un comportement indéfini si ptr ne pointe pas vers un objet valide.
    En fait, avec un type simple comme donnée en exemple au début du post, le code généré par Visual et gcc (windows) est le même quelque soit l'écriture et correspond uniquement à récupérer la valeur de prt. Donc, il n'y a pas de déréférencement fait sur prt. L'exemple &*ptr ne plante pas même si ptr n'est pas initialisé. C'est une optimisation du compilo mais j'avoue que je ne m'y fierait pas et que j'éviterais cette forme d'écriture.

  9. #9
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    En pratique, oui, ça ne fait rien.
    D'après le standard, néanmoins, c'est un comportement indéfini de déréferencer un pointeur non initialisé ou nul, qu'on utilise le résultat avec & ou non.

  10. #10
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Simplement en lire la valeur, sans la déréférencer, est déjà non défini par le standard, et donc, en mode chipotage, les écritures *(&ptr) et ptr ont aussi un problème dans ce cas.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  11. #11
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Simplement en lire la valeur, sans la déréférencer, est déjà non défini par le standard, et donc, en mode chipotage, les écritures *(&ptr) et ptr ont aussi un problème dans ce cas.
    ?Comprend pas?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if(ptr==NULL){// je lis la valeur sans la déréférencer et c'est pas un pb?
    }

  12. #12
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    ?Comprend pas?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if(ptr==NULL){// je lis la valeur sans la déréférencer et c'est pas un pb?
    }
    C'est un probleme si ptr n'est pas initialise ou est invalide. Par exemple apres

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ptr = new ?;
    delete ptr;
    C'est du comportement indefini. (Il y a des architectures ou charger un pointeur invalide dans un registre peut generer une interruption. Les x86 en mode protege par exemple si on utilise les segments.)

  13. #13
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    C'est un probleme si ptr n'est pas initialise ou est invalide. Par exemple apres

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ptr = new ?;
    delete ptr;
    C'est du comportement indefini. (Il y a des architectures ou charger un pointeur invalide dans un registre peut generer une interruption. Les x86 en mode protege par exemple si on utilise les segments.)
    Je suis dur de la feuille car je ne comprends pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int *ptr;
    if(ptr!=NULL){// Là ca plante?
       ptr=NULL;
    }

  14. #14
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Je suis dur de la feuille car je ne comprends pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int *ptr;
    if(ptr!=NULL){// Là ca plante?
       ptr=NULL;
    }
    Oui.

  15. #15
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Oui.
    Bon, ben merci: il est toujours temps d'apprendre quelque chose!

    Mais, du coup, c'est un peu le serpent qui se mort la queue:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int *prt;
    prt = NULL;// là ca marche?

  16. #16
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 394
    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 394
    Par défaut
    Ben oui ça marche: Ce n'est pas une lecture, c'est une écriture.
    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.

  17. #17
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    J'avais bêtement toujours cru qu'un pointeur ca restait un emplacement mémoire comme un autre qui prenait son sens qu'au moment du déréférencement: là effectivement, on fait un saut vers un autre emplacement mémorie, celui dont l'adresse est contenue dans le pointeur.
    Mais, là, dans ce genre d'architecture, cela signifie que les pointeurs sont dans des espaces mémoires différents que les autres variables? Sinon, comment sait-on si on charge un pointeur dans un registre ou un entier par exemple?

  18. #18
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 394
    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 394
    Par défaut
    Le problème, c'est que le seul fait de lire une valeur non-initialisée est toujours un comportement indéfini, quel que soit le type de la variable. Car selon la plate-forme, il reste toujours la possibilité de tomber sur une "trap value", une représentation qu'il est illégal d'avoir dans un registre.

    http://blogs.msdn.com/oldnewthing/ar...2/8679191.aspx
    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.

  19. #19
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Ok, je comprends. Merci pour ces infos. Je regarde ton lien.

  20. #20
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Le problème, c'est que le seul fait de lire une valeur non-initialisée est toujours un comportement indéfini, quel que soit le type de la variable. Car selon la plate-forme, il reste toujours la possibilité de tomber sur une "trap value", une représentation qu'il est illégal d'avoir dans un registre.

    http://blogs.msdn.com/oldnewthing/ar...2/8679191.aspx
    Ce qui est particulier pour les pointeurs, c'est qu'une action comme delete ou le retour d'une fonction (dans le cas ou on pointe vers une variable locale a cette fonction) peut faire passer le schema de bits d'une valeur valide a une valeur qui trappe.

Discussions similaires

  1. [LG]Les pointeurs: Forme en "Anneaux"
    Par k o D dans le forum Langage
    Réponses: 4
    Dernier message: 20/10/2004, 07h29
  2. Réponses: 4
    Dernier message: 13/08/2004, 18h39
  3. [TTreeView] Problème avec les pointeurs d'objet
    Par BlackWood dans le forum Composants VCL
    Réponses: 2
    Dernier message: 02/07/2004, 14h31
  4. pointeurs, toujours les pointeurs :/
    Par giviz dans le forum C
    Réponses: 16
    Dernier message: 08/10/2003, 15h02
  5. Pb de débutant sur les pointeurs!!!
    Par benji17c dans le forum C
    Réponses: 6
    Dernier message: 30/09/2003, 17h50

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