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 :

Priorité des opérateurs * et ++


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut Priorité des opérateurs * et ++
    Bonjour,

    Je lisais hier soir et ce matin le chapitre 5 sur les pointeurs et les tableaux dans le K&R (j'ai la 2e édition en français, chez Dunod. Je citerai les pages dans la suite, si vous avez une édition différente, dommage...).

    A la page 93, ils expliquent que (*p)++ incrémente le contenu du pointeur p et que les parenthèses sont obligatoires sous peine d'incrémenter le pointeur p. En effet, les opérateurs unaires s'évaluent de la droite vers la gauche.

    Ensuite, à la page 104, ils disent que *p++ = val; met val sur la pile. J'en déduis que le contenu de p prend la valeur de val et que p est incrémenté.

    Or, j'ai l'impression que les deux codes sont contradictoires. En suivant la règle du 1er code, j'aurais tendance à penser que le code 2 revient à :
    • incrémenter le pointeur p (car l'opérateur unaire ++ est à droite et s'évalue en premier)
    • le contenu de p ainsi décalé prend la valeur de val


    Qu'est ce que j'ai mal compris ?

  2. #2
    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
    Or, j'ai l'impression que les deux codes sont contradictoires. En suivant la règle du 1er code, j'aurais tendance à penser que le code 2 revient à :
    incrémenter le pointeur p (car l'opérateur unaire ++ est à droite et s'évalue en premier)
    le contenu de p ainsi décalé prend la valeur de val
    Non, cela signifie que l'opérateur ++ s'applique à p et non à *p. Les règles de priorité et d'associativité déterminent à quoi s'applique l'opérateur, cela n'a pas de rapport avec l'ordre d'évaluation des opérandes (qui sauf quelques exceptions ( opérateurs (virgule) , &&, ||, ?:) n'est pas déterminé).
    Comme il s'agit ici d'un post incrément, p sera modifié après l'évaluation de p.
    Donc on a
    -1 Evaluation de la valeur de p
    -2 Evaluation de val
    -3 Incrément du contenu de p
    -4 Mise de val à l'adresse évaluée en 1

    Sur l'ordre des étapes, on sait seulement que 3 est postérieur à 1 et 4 est postérieur à 1 et 2. On peut avoir 1-2-3-4 ou 2-1-3-4 ou 1-2-4-3 ou 2-1-4-3 ou ...
    Mais comme ici le résultat obtenu sera le même quel que soit l'ordre, l'expression est bien formée.

  3. #3
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Effectivement avec les étapes détaillées, c'est beaucoup plus clair ! Merci ! En fait, c'est (surtout) l'étape 4 qui me manquait. On garde la valeur trouvée à l'étape 1.

    Si j'ai bien compris :

    implique que a contient le contenu de p avant incrémentation et que p est incrémenté après exécution.

    implique que le contenu de p est incrémenté et que a contient ce nouveau contenu.

  4. #4
    Membre émérite
    Avatar de bpy1401
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2003
    Messages
    511
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Eure (Haute Normandie)

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

    Informations forums :
    Inscription : Mars 2003
    Messages : 511
    Par défaut
    Bonjour à tous,

    un conseil , ne faite jamais confiance à votre connaissance de la priorité des opérateurs, moi, je préfère la forcer avec les parenthèse. Ca évite les bug, et facilite la relecture.
    Page sur Developpez : http://pbriand.developpez.com

  5. #5
    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
    Dans les deux cas, ce n'est pas le contenu de p qui est placé dans a, mais la valeur qui est à l'adresse contenue dans p

    Le premier équivaut à a = *(p++);. a contiendra ce qui est à l'adresse contenue dans p et le contenu de p est incrémenté (donc p contient alors l'adresse de l'élément suivant)

    Le second a = (*p)++;. a contiendra la valeur qui est à l'adresse contenue dans p et cette valeur est incrémentée

    Un exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int main(void)
    {
      int tab[] = {1,5,10,15};
      int * p = tab;
      int a;
     
      a = *p++;    // a = 1 , tab inchangé, p == tab+1
      a = *p;      // a = 5 , On vérifie p == tab+1
      a = (*p)++;  // a = 5 , *p == tab[1]== *(tab+1) a changé : tab = {1,6,10,15}, p inchangé : p==tab+1
      a = *p;      // a = 6 , On vérifie p == tab+1
      return 0;
    }

  6. #6
    Membre chevronné
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2012
    Messages
    190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Janvier 2012
    Messages : 190
    Par défaut
    @bpy1401 : il faut aussi pouvoir lire le code des autres (et parfois la réciproque).

    j'ai trouvé dans le draft de C99
    EXAMPLE 7 The grouping of an expression does not completely determine its evaluation. In the following fragment
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #include <stdio.h>
    int sum;
    char *p;
    /* ... */
    sum = sum * 10 - '0' + (*p++ = getchar());
    the expression statement is grouped as if it were written as
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sum = (((sum * 10) - '0') + ((*(p++)) = (getchar())));
    but the actual increment of p can occur at any time between the previous sequence point and the next sequence point (the ;), and the call to getchar can occur at any point prior to the need of its returned value.
    ça me laisse songeur ...

    A+

  7. #7
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Ce qui sous-entend que mettre p++ entre parenthèses ne garantit pas que ce sera incrémenté avant qu'on évalue p ?

    Ce sujet et aussi les écritures (ultra compactes, sans accolades aux IF et FOR, l'utilisation massive de ++ et --, etc. ) que j'ai lu dans le K&R m'ont confirmé dans mon opinion qu'un code sur plusieurs lignes est plus sûr et plus compréhensible qu'un code compact. A moins d'extrêmement bien maitriser les finesses du langage et que les gens qui liront votre code également...

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

Discussions similaires

  1. Priorité des opérateurs % et ++
    Par G3G3 dans le forum Débuter
    Réponses: 16
    Dernier message: 12/02/2008, 09h40
  2. [OCaml & F#] Priorité des opérateurs
    Par SpiceGuid dans le forum Caml
    Réponses: 7
    Dernier message: 01/01/2008, 15h00
  3. priorité des opérateurs
    Par new_wave dans le forum SQL
    Réponses: 13
    Dernier message: 08/11/2007, 21h44
  4. Priorité des opérateurs
    Par neuromencien dans le forum Langage
    Réponses: 3
    Dernier message: 14/05/2007, 17h06
  5. Réponses: 3
    Dernier message: 31/08/2006, 10h39

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