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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre actif
    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
    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
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 476
    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 476
    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 actif
    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
    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 : 276
Taille : 15,6 Ko

  4. #4
    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
    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
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 476
    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 476
    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
    Membre averti
    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
    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 actif
    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
    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;  
    }

+ 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