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 :

Pointeurs valeurs inattendues


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 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 47
    Par défaut Pointeurs valeurs inattendues
    Bonjour,

    J'ai un problème avec le programme suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    main()
       {
          int A = 1;
          int B = 2;
          int C = 3;
          int *P1, *P2;
          P1=&A;
          P2=&C;
          *P1=(*P2)++;
    	printf("%d\n",A);
    }
    D'après moi A=4 et C reste égal à 3.
    En effet *P1=(*P2)++; équivaut à :
    A=C+1;
    donc A=4 et C ne change pas...
    Pouvez-vous m'expliquer pourquoi on obtient A=3 et C=4 ?


    Merci par avance

  2. #2
    Invité(e)
    Invité(e)
    Par défaut
    Bonjour,
    ++ a la priorité sur =, mais ++ est un post incrément : il s'effectuera après l'instruction dans laquelle il est.

    Donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Pas 1 : *P1 = *P2; -> A = 3;
    Pas 2 : *P2++; -> C =4;

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 47
    Par défaut
    salut mabu,
    mais ici, il n'y a pas de boucle for ou while ?
    Moi je pensais que i++ était équivalent à i+1 (notre prof nous à dis ça un jour)
    peut-être que ce n'est pas tout le temps valable ^^

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Par défaut
    mais ici, il n'y a pas de boucle for ou while ?
    Quel rapport ?

    Moi je pensais que i++ était équivalent à i+1 (notre prof nous à dis ça un jour)
    Non, l'opérateur ++ incrémente de 1 la variable (ou le pointeur, si c'en est un).

    Les deux instructions sont équivalentes :

  5. #5
    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
    i++ n'est pas équivalent à i+1.

    Ce serait équivalent à une fonction qui fait ceci:
    Code C : 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
    int PostIncrementInt(int *pi)
    {
    	int ret = *pi;
    	*pi = *pi + 1;
    	return ret;
    }
     
    int main(void)
    {
    	int a = 1;
    	int b;
    	b = PostIncrementInt(&a);
     
    	printf("%d %d\n", a, b);
    	return 0;
    }
    On voit avec cette traduction que l'opérateur ++ retourne l'ancienne valeur de i.

    Voyons ce que ça donnerait dans ton code:
    Code C : 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 PostIncrementInt(int *pi)
    {
    	int ret = *pi;
    	*pi = *pi + 1;
    	return ret;
    }
     
    int main(void)
    {
    	int A = 1;
    	int B = 2;
    	int C = 3;
    	int *P1 = &A;
    	int *P2 = &C;
     
    	*P1 = PostIncrementInt(&(*P2)); /* ou plus simplement PostIncrementInt(P2) */
    	printf("%d %d %d\n", A, B, C);
    	return 0;
    }
    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.

  6. #6
    Membre confirmé Avatar de fomazou
    Inscrit en
    Mars 2004
    Messages
    220
    Détails du profil
    Informations forums :
    Inscription : Mars 2004
    Messages : 220
    Par défaut
    Moi je pensais que i++ était équivalent à i+1 (notre prof nous à dis ça un jour)
    peut-être que ce n'est pas tout le temps valable ^^


    ça ne serai pas pour le bohneur des programmeur qu'une expression change de sens selon l'endroit.

    i++ n'est même pas équivalent à i=i+1 on peut dire pseudoequivalent. puisque i++ et ++i sont différents et pour incrémente tous de 1 comme i=i+1.
    la diff est que i++ et ++i sont des expressions(donc peuvent faire partir d'une instruction) l'un est évaluer avant d'être incrémenté et l'autre incrémenté avant d'être évalué

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 47
    Par défaut
    Merci à vous, je vais étudier tout ça

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 47
    Par défaut
    Ça y est j'ai compris la post-incrémentation,mais j'obtiens toujours des valeurs inattendues dans le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    main()
    {
     
    	int A[50];
    	int *p1,*p2;
    	int N;
    	int temp;
    	printf("combien d'element aura le tableau (max:50)");
    	scanf("%d",&N);
    	/*affichage*/
    	for (p1=A;p1<A+N;p1++)
    		printf("resultat %d %d  %d\n\n",p1-A,p1,A);
    }
    voici ce que j'obtiens :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
                  p1-A        p1        A
     
    resutat       0      1244828   1244828  (ça fonctionne)
    resultat      1       1244832   1244828  (ça fonctionne plus)
    resultat      2       1244836   1244828
    c'est difficile

  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 gbsatti Voir le message
    J'ai un problème avec le programme suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    main()
       {
          int A = 1;
          int B = 2;
          int C = 3;
          int *P1, *P2;
          P1=&A;
          P2=&C;
          *P1=(*P2)++;
    	printf("%d\n",A);
    }
    D'après moi A=4 et C reste égal à 3.
    En effet *P1=(*P2)++; équivaut à :
    A=C+1;
    donc A=4 et C ne change pas...
    Pouvez-vous m'expliquer pourquoi on obtient A=3 et C=4 ?
    Ton code est incomplet...
    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
     
     
    -------------- Build: Debug in hello ---------------
     
    Compiling: main.c
    Linking console executable: bin\Debug\hello.exe
    C:\dev\hello\main.c:2: warning: return type defaults to `int'
    C:\dev\hello\main.c:2: warning: function declaration isn't a prototype
    C:\dev\hello\main.c: In function `main':
    C:\dev\hello\main.c:10: warning: implicit declaration of function `printf'
    C:\dev\hello\main.c:4: warning: unused variable `B'
    C:\dev\hello\main.c:11: warning: control reaches end of non-void function
    Output size is 17.05 KB
    Process terminated with status 0 (0 minutes, 1 seconds)
    0 errors, 5 warnings
    Ceci est complet, mais incorrect :
    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
     
    #include <stdio.h>
     
    int main (void)
    {
       int A = 1;
       int B = 2;
       int C = 3;
       int *P1, *P2;
       P1 = &A; /* OK */
       P2 = &C; /* OK */
       *P1 = (*P2)++; /* Comportement indéfini. on ne sait pas quand est evalue le ++ */
       printf ("%d\n", A);
     
       return 0;
    }
    Le code correct est probablement :
    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
     
    #include <stdio.h>
     
    int main (void)
    {
       int A = 1;
       int B = 2;
       int C = 3;
       int *P1, *P2;
       P1 = &A; /* OK */
       P2 = &C; /* OK */
       (*P2)++;
       *P1 = *P2;
       printf ("%d\n", A);
     
       return 0;
    }
    qui donne 4.

    Nota : B n'est pas utilisée.

    Pour avoir un comportement clair, le mieux est de n'utiliser ++ ou -- que dans une expression unaire (i++; --i; etc.)

  10. #10
    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
    Sauf qu'à ma connaissance, ce comportement-là n'est PAS indéfini: Il n'y a qu'un seul ++, la même variable n'est pas modifiée deux fois dans l'expression, donc le résultat est garanti.
    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.

  11. #11
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       *P1 = (*P2)++; /* Comportement indéfini. on ne sait pas quand est evalue le ++ */
    Citation Envoyé par Médinoc Voir le message
    Sauf qu'à ma connaissance, ce comportement-là n'est PAS indéfini: Il n'y a qu'un seul ++, la même variable n'est pas modifiée deux fois dans l'expression, donc le résultat est garanti.
    +1 (sauf si P1 et P2 pointent sur le même objet)

  12. #12
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 47
    Par défaut
    Merci à vous j'ai compris ça
    a+

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 03/05/2012, 08h37
  2. Paramètres de fonction : pointeurs ou valeurs ?
    Par Xandar dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 30/11/2005, 16h50
  3. Réponses: 3
    Dernier message: 20/09/2005, 08h59
  4. Réponses: 3
    Dernier message: 11/08/2005, 15h54
  5. Echange de valeurs par pointeur et réf
    Par smag dans le forum C++
    Réponses: 6
    Dernier message: 01/03/2005, 18h39

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