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

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 81
    Points : 65
    Points
    65
    Par défaut Priorité des opérateurs % et ++
    Bonjour,

    J'ai une petite question concernant la priorité des opérateurs modulo et d'incrémentation. J'ai regardé le tableau donnant les priorités des opérateurs % et ++ : http://c.developpez.com/cours/bernar...ne/node101.php
    mais je n'arrive pas à comprendre les résultats du code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int i = 9;      // i = 9,    Ok
    i = (i++)%10;  // i = 10,     ???
    ++ étant prioritaire sur % lui-même prioritaire sur =, je pensais que les opérations se déroulaient dans cet ordre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int i = 9; 
    i++; 
    i = i%10;     // i = 0
    Et pourtant il semble qu'elles soient exécutées comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int i = 9; 
    i = i%10; 
    i++;   // i = 10
    Je dois avouer que je n'y comprends pas grand chose, même les parenthèses n'y font rien. Si quelqu'un pouvait m'expliquer, je l'en remercie d'avance...

  2. #2
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    On s'en fout des priorités. Dans i = (i++) % 10, i++ est d'abord évalué : ça vaut 9 (puisque i = 9), ensuite 9 % 10 vaut 9 et on affecte ce résultat à i donc i = 9. Mais à la fin de l'instruction i est incrémenté (i++), on a alors finalement i = 10.

  3. #3
    Inactif  
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 958
    Détails du profil
    Informations personnelles :
    Âge : 58
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 958
    Points : 2 467
    Points
    2 467
    Par défaut
    En règle générale : n'utilises pas ++ sur une variable que tu utilises à gauche et à droite de l'affectation.

    Dans le cours que tu mentionnes :
    À part quelques exceptions, l'ordre d'évaluation des opérandes d'un opérateur n'est pas spécifié par le langage. Ceci a pour conséquence que le programmeur doit faire extrêmement attention aux effets de bords dans les expressions. Par exemple, l'instruction :

    t[i] = f();

    où la fonction f modifie la valeur de i a un comportement indéterminé : il est impossible de savoir si la valeur prise pour indexer t sera celle de i avant ou après l'appel à f.
    Ce qui est prioritaire c'est l'obtention de la valeur. Dans le cas de (++i), ce ne peut être obtenu qu'après avoir affecté l'incrément. Mais de le cas (i++) l'incrément étant calculé après ça n'est pas obligatoire. Et tu rendres dans le genre de détail qui me font toujours écrire des expressions sans ++ ou -- sauf dans les cas où on peut les remplacer par (+= 1). Ce sont des nids à pièges.

  4. #4
    Inactif  
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 958
    Détails du profil
    Informations personnelles :
    Âge : 58
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 958
    Points : 2 467
    Points
    2 467
    Par défaut
    En même temps

  5. #5
    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
    Et j'en rajoute une couche:
    • Tout ce qui est sous la forme "i = i++" est un comportement indéterminé.
    • Tout ce qui est sous la forme "foo( i++, i++ )" est également un comportement indéterminé.
    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
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    d'ou l'interet, que je conseille TOUJOURS, d'eviter les increments "compactes" dans les expressions (en dehors des boucles, ou de certains algos tres specifiques (deplacement dans un tableau (et encore )), et de mettre des parentheses PARTOUT ou il y a PLUSIEURS conditions ou evaluations...

    NE JAMAIS PRESUMER des ordres de priorite.... sauf dans le cas des ET (&&) ou l'on sait que l'on n'atteitn jamais la deuxieme condition si la premiere n'est pas remplie....

    En bref, est-ce vraiment si penible d'ecrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    i = 9
    i = i + 1
    i = i % 10
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    i = 9
    i = i  % 10
    i = i + 1
    ???

    et est-ce vraiment penible d'ecrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ( (a == b) && ((c == d) || (g == f)) )
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  7. #7
    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
    Citation Envoyé par souviron34 Voir le message
    En bref, est-ce vraiment si penible d'ecrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    i = 9
    i = i + 1
    i = i % 10
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    i = 9
    i = i  % 10
    i = i + 1
    Oui. Il est à la fois plus rapide et plus simple de faire ceci:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    i = 9;
    i++;
    i %= 10;
    Et tu remarqueras que cela ne fait aucune présomption sur les priorités: Ce code est 100% fiable.

    et est-ce vraiment penible d'ecrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ( (a == b) && ((c == d) || (g = f)) )
    Non, c'est ce que je fais dès qu'utilise une expression un tant soi peu complexe.
    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.

  8. #8
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Oui. Il est à la fois plus rapide et plus simple de faire ceci:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    i = 9;
    i++;
    i %= 10;
    Et tu remarqueras que cela ne fait aucune présomption sur les priorités: Ce code est 100% fiable.
    .


    franchement : je vois ca dans un code industriel, je te mets un beau zero pointe
    (je sais que ca se fait, je sais que le langage le permet, mais je le deconseille FORTEMENT)
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  9. #9
    Membre habitué Avatar de emprex
    Homme Profil pro
    auto-entrepreneur
    Inscrit en
    Octobre 2007
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : auto-entrepreneur
    Secteur : Services à domicile

    Informations forums :
    Inscription : Octobre 2007
    Messages : 219
    Points : 199
    Points
    199
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include <stdio.h>
    int main(void){
    int i = 9;
    i = (++i)%10;
    printf("i vaut = %d\n",i);
    return 0;
    }
    dans cette configuration nous avons le bon résultat. Mais est ce correcte?

  10. #10
    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
    Je crois bien que non, c'est toujours indéfini. Mais ça devrait marcher dans la plupart des implémentations, sans aucune garantie.
    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 é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
    Corrigé:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include <stdio.h>
    int main(void) {
    	int i = 9;
    	++i;
    	i =  i %10; /* ou i %= 10 */
    	printf("i vaut = %d\n",i);
    	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.

  12. #12
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Et j'en rajoute une couche:
    • Tout ce qui est sous la forme "i = i++" est un comportement indéterminé.
    • Tout ce qui est sous la forme "foo( i++, i++ )" est également un comportement indéterminé.
    tu as entièrement raison, et cette écriture est totalement à proscrire.

    souviron34 :
    Envoyé par Médinoc
    Oui. Il est à la fois plus rapide et plus simple de faire ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    i = 9;
    i++;
    i %= 10;
    Et tu remarqueras que cela ne fait aucune présomption sur les priorités: Ce code est 100% fiable.
    franchement : je vois ca dans un code industriel, je te mets un beau zero pointe
    (je sais que ca se fait, je sais que le langage le permet, mais je le deconseille FORTEMENT)
    Et pourquoi ? C'est une position dogmatique ? Le code est clair, fiable et sans ambiguïté
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  13. #13
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    parce qu'en general, si on est adepte de ce genre d'ecriture, on arrive tres facilement au code obfusque....

    Donc OUI c'est dogmatique....

    Mais pragmatique....

    Car le gars (ca m'est arrive, c'est pour ca que je le dit) qui fait de la maintenance sur site , dans le contexte d'une appli largement distribuee, avec contraintes de temps de delais d'intervention, n'a pas forcement a sa disposition ni toute la connaissance de la subtilite des notations, ni le temps de decoder une ligne bourree de += *=, %= , ++, (++)*(--), etc etc....

    Donc, regle d'or d'un code industriel : lisibilite IMMEDIATE sans prise de tete...

    Et comme c'est rigoureusement equivalent comme code genere, pourquoi faire complique quand on peut faire simple ???

    un exemple : un contrat de maintenance prevoyant 4h de delai d'intervention MAX (le cas des applis medicales en milieu hospitalier). Une appli de traitement d'images sur un scanner.... 200 ou 300 mille lignes de code.... si les traitements sont ecrits comme ca....
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  14. #14
    Inactif  
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 958
    Détails du profil
    Informations personnelles :
    Âge : 58
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 958
    Points : 2 467
    Points
    2 467
    Par défaut
    Je pense que le code présenté par Médinoc est largement acceptable et que Souviron y va un peu fort

    Cependant comme je disais personnellement j'évite ++ et --.
    Et j'admet que %= n'est pas très agréable. Mais j'apprécie += ou *= par exemple.

  15. #15
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Moi, j'ai rien contre les opérateurs ++, --, += et compagnie mais il ne faut pas en abuser (tout excès fait défaut !). Par exemple : : acceptable.
    Mais pas ou comme dans l'exemple du P.O.

  16. #16
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Melem Voir le message
    Mais pas ou comme dans l'exemple du P.O.
    De toute manière ici, ce n'est pas une question d'accepter la notation ou pas. Le comportement est indéterminé. Point.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  17. #17
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Citation Envoyé par Thierry Chappuis
    De toute manière ici, ce n'est pas une question d'accepter la notation ou pas. Le comportement est indéterminé. Point.
    C'est une des raisons pour la quelle il faut éviter ce genre d'écriture .

Discussions similaires

  1. priorité des opérateurs
    Par new_wave dans le forum Langage
    Réponses: 3
    Dernier message: 02/12/2008, 12h09
  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