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 :

Manipulation des pointeurs


Sujet :

C

  1. #1
    Membre à l'essai
    Homme Profil pro
    Manager
    Inscrit en
    Avril 2009
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Gabon

    Informations professionnelles :
    Activité : Manager

    Informations forums :
    Inscription : Avril 2009
    Messages : 25
    Points : 22
    Points
    22
    Par défaut Manipulation des pointeurs
    Bonsoir !
    Le programme devrait afficher le contenu et les adresses des variable.
    Mais à l'exécution, il plante (Version 1)!

    A la version 2, quand je modifie le programme, il affiche un résultat.
    Pourrais avoir des orientations dans la premiere version ?


    Version 1
    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
     
    int main()
    {
        int *a, *b, *c;
     
        *a = 4;
        *b = 5;
     
        printf("contenu *a : %d, addresse a : %p\n", *a, a);
        printf("Contenu *b : %d, addresse b : %p\n", *b, b);
     
        *c = *a;
        *a = *b;
        *b = *c;
     
        printf("Contenu *a : %d, addresse a: %p\n", *a, a);
        printf("Contenu *b : %d, addresse b: %p\n", *b, b);
     
        do{}while(kbhit() == 0);
        return 0;
    }
    Version 2

    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
     
     
    int main()
    {
        int *a, *b, *c;
     
        *a = 4;
        *b = 5;
     
        printf("contenu *a : %d, addresse a : %p\n", a, a);
        printf("Contenu *b : %d, addresse b : %p\n", b, b);
     
        c = a;
        a = b;
        b = c;
     
        printf("Contenu *a : %d, addresse a: %p\n", a, a);
        printf("Contenu *b : %d, addresse b: %p\n", b, b);
     
        do{}while(kbhit() == 0);
        return 0;
    }
    [/QUOTE]

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 373
    Points : 23 629
    Points
    23 629
    Par défaut
    Bonjour,

    Tu déclares des pointeurs (sur des entiers) mais au départ, ceux-ci sont complètement indéfinis et ne pointent donc sur rien de valide (leur valeur dépend de ce qui se trouvait à l'emplacement mémoire qui leur a ensuite été réservé). Quand tu déréférences ensuite ces pointeurs pour affecter une valeur telle que « 3 » ou « 4 », celles-ci vont donc prendre place n'importe où en mémoire et très probablement déclencher une segfault.

    En théorie, ton second programme devrait planter comme le premier, sauf que tu limites déjà les dégâts en permutant le contenu des pointeurs eux-mêmes (qui existent bel et bien) et pas ce qu'ils sont censés pointer. Néanmoins, les premières affectation en début de programme restent invalides. Mais s'il se trouve que la valeur initiale des pointeurs renvoie vers l'intérieur de l'espace du processus, alors le système n'y trouvera rien à redire, même s'il y a de fortes chances pour que tu aies corrompu des données de cette façon, qui seront plus tard source de bugs très pénibles à isoler et à corriger.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Manager
    Inscrit en
    Avril 2009
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Gabon

    Informations professionnelles :
    Activité : Manager

    Informations forums :
    Inscription : Avril 2009
    Messages : 25
    Points : 22
    Points
    22
    Par défaut Manipulation des pointeurs
    Obsidian : j'ai pas l'air de bien comprendre tes explications !
    Quel lien directe y'a t'il entre la déclaration des pointeurs et lors de l'affectation des valeurs ?
    Aussi, avec un peu de débrouillardise, je change la place de b et c, il me semble que le programme donne un meilleur résultat !
    Mais j'ai pas d'explications !!!

    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 *a, *c, *b; 
                                   
        *a = 4;
        *b = 5;
    
        printf("contenu de *a : %d, addresse de a : %p\n", *a, a);
        printf("Contenu de *b : %d, addresse de b : %p\n", *b, b);
        printf("\n");
        printf("Après permutation : \n");
        c = a;
        a = b;
        b = c;
        printf("\n");
        printf("Contenu de *a : %d, addresse de a: %p\n", *a, a);
        printf("Contenu de *b : %d, addresse de b: %p\n", *b, b);
    Nom : img_c.PNG
Affichages : 257
Taille : 15,6 Ko

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Tes pointeurs sont non-initialisés, leur déréférencement est donc un comportement indéfini: tout peut arriver.
    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.

  5. #5
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 373
    Points : 23 629
    Points
    23 629
    Par défaut
    Citation Envoyé par thima137 Voir le message
    Obsidian : j'ai pas l'air de bien comprendre tes explications !
    Quel lien directe y'a t'il entre la déclaration des pointeurs et lors de l'affectation des valeurs ?
    Le fait de déclarer un pointeur « *a » ne déclare pas implicitement une variable « b » pointée par lui.

    Quand tu fais une affectation avec « *a = 4 », tu n'affectes pas la valeur « 4 » au pointeur lui-même mais à ce qu'il pointe. Et il se trouve qu'au départ, ton pointeur ne pointe rien de valide. Plus précisément, tu déclares un pointeur qui est alors « prêt à être utilisé », c'est-à-dire qui attend que tu le fasses pointer quelque part.

    D'autre part, quand tu déclares une variable locale, qu'il s'agisse d'un pointeur ou d'une variable ordinaire, tu ne fais que lui réserver de l'espace (dans la pile). Cela signifie que la valeur initiale d'une variable locale fraîchement créée ne sera pas « 0 » par défaut (contrairement aux variables globales et statiques) mais une valeur complètement indéterminée, correspondant en fait à ce qui se trouve en mémoire à l'endroit réservé. Si tu déréférences le pointeur à ce moment-là et que tu demandes à déposer quelque chose à l'endroit où il pointe, ton programme va donc déposer cette chose à un endroit complètement indéterminé en mémoire. Soit c'est en dehors de l'espace alloué à ton processus et là, le micro-processeur s'en rend compte et déclenche une segfault, soit c'est à l'intérieur et dans ce cas, cela relève de ta propre responsabilité. Tu viens alors de corrompre tes propres données sans même t'en rendre compte, ce qui peut provoquer un comportement indéterminé, parfois bien plus tard.

    Voici un exemple simple :

    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
    #include <stdio.h>
     
    int main (void)
    {
        int a;
        int *p;
     
        a = 5;   /* Mets 5 dans a */
        p = &a;  /* Mets l'adresse de a dans p */
     
        printf ("Valeur de a : %d\n",a);
        printf ("Contenu de p : %p\n",p);
        printf ("Valeur de ce qui est pointé par p : %d\n",*p);
     
        *p = 7; /* Modifie ce qui est pointé par p */
     
        printf ("Valeur de a : %d\n",a);
        printf ("Contenu de p : %p\n",p);
        printf ("Valeur de ce qui est pointé par p : %d\n",*p);
     
        return 0;  
    }
    On obtient :

    Valeur de a : 5
    Contenu de p : 0x7ffc02412b64
    Valeur de ce qui est pointé par p : 5
    Valeur de a : 7
    Contenu de p : 0x7ffc02412b64
    Valeur de ce qui est pointé par p : 7
    Maintenant, je supprime volontairement la variable « a » et, par conséquent, je suis obligé de supprimer également toutes les lignes qui s'y réfèrent (le reste du programme est inchangé) :

    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
    #include <stdio.h>
     
    int main (void)
    {
        /* Ligne supprimée */
        int *p;
     
        /* Ligne supprimée */
        /* Ligne supprimée */
     
        /* Ligne supprimée */
        printf ("Contenu de p : %p\n",p);
        printf ("Valeur de ce qui est pointé par p : %d\n",*p);
     
        *p = 7; /* Modifie ce qui est pointé par p */
     
        /* Ligne supprimée */
        printf ("Contenu de p : %p\n",p);
        printf ("Valeur de ce qui est pointé par p : %d\n",*p);
     
        return 0;  
    }
    À ton avis, quel résultat va-t-on obtenir ?

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2014
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2014
    Messages : 17
    Points : 26
    Points
    26
    Par défaut
    *P = 4; correspond à dire :
    P -> ("une variable" = 4)
    ( -> signifie "pointe sur")

    Si tu ne définis pas "une variable", il risque d'y avoir des problème comme te l'indique Obsidian car c'est l'ordinateur qui va le faire à ta place, ce qui est source d'erreur.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Manager
    Inscrit en
    Avril 2009
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Gabon

    Informations professionnelles :
    Activité : Manager

    Informations forums :
    Inscription : Avril 2009
    Messages : 25
    Points : 22
    Points
    22
    Par défaut Manipulation des pointeurs
    Pour ce code :
    Je comprends bien que : *p affichera 7, après l'affectation *p=7, c'est juste !!!
    Par contre je comprends pas pourquoi pour: *p sans avoir affecté une valeur, il choisit d'afficher 0 ?
    Est-ce parce que aucune valeur n'a été pointé vers la variable pointeur *p ?
    Si c'est le cas, devrais-je donc comprendre que pour manipuler un pointeur il faudra que je précise une variable pointé ?


    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
    #include <stdio.h>
     
    int main (void)
    {
        /* Ligne supprimée */
        int *p;
     
        /* Ligne supprimée */
        /* Ligne supprimée */
     
        /* Ligne supprimée */
        printf ("Contenu de p : %p\n",p);
        printf ("Valeur de ce qui est pointé par p : %d\n",*p);
     
        *p = 7; /* Modifie ce qui est pointé par p */
     
        /* Ligne supprimée */
        printf ("Contenu de p : %p\n",p);
        printf ("Valeur de ce qui est pointé par p : %d\n",*p);
     
        return 0;  
    }

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    C'est un comportement indéfini. Tout peut arriver, y compris l'apparition de démons dans ton nez.
    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.

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 986
    Points
    30 986
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par thima137 Voir le message
    Si c'est le cas, devrais-je donc comprendre que pour manipuler un pointeur il faudra que je précise une variable pointé ?
    Exactement. Et ce n'est pas la peine de mettre ce smiley sarcastique. C'est plutôt obligatoire, quand on veut aller voir quelque chose, de savoir où il faut aller. Ben là, c'est pareil. Si tu veux aller voir le contenu d'une adresse, il est alors obligatoire, déjà, de connaitre cette adresse !!!

    De façon plus générale: tu n'as pas le droit de manipuler "*p" si tu n'as pas écrit au-moins une fois en amont de ton code p=quelque chose. Et bien entendu, il faut que ce "quelque chose" soit quelque chose de correct. Soit l'adresse d'une autre variable, soit une adresse donnée par une fonction dédiée (malloc, shmat, etc) soit NULL.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Membre à l'essai
    Homme Profil pro
    Manager
    Inscrit en
    Avril 2009
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Gabon

    Informations professionnelles :
    Activité : Manager

    Informations forums :
    Inscription : Avril 2009
    Messages : 25
    Points : 22
    Points
    22
    Par défaut Manipulation des pointeurs
    Ok ! C'est pigé !!!
    Merci à tous !

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

Discussions similaires

  1. Manipulation des pointeurs sur des array of record
    Par kracter56 dans le forum Débuter
    Réponses: 8
    Dernier message: 13/04/2012, 09h58
  2. Manipulation des pointeurs
    Par AQkinkin dans le forum Windows Forms
    Réponses: 1
    Dernier message: 28/08/2009, 10h32
  3. Réponses: 1
    Dernier message: 27/11/2005, 14h30
  4. Manipulation des handle contexte
    Par rockbiker dans le forum DirectX
    Réponses: 1
    Dernier message: 09/05/2003, 18h51
  5. Fonctions de manipulation des chaines et des dates
    Par Fares BELHAOUAS dans le forum Débuter
    Réponses: 3
    Dernier message: 09/11/2002, 22h43

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