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 :

Différence entre ++i et i++


Sujet :

C

  1. #1
    Expert confirmé
    Différence entre ++i et i++
    Bonjour,

    Je me lance dans la programmation C et je sais que pour incrémenter une variable, on utilise i++ mais en parcourant le net, j'ai vu une autre syntaxe bizarre ++i et je me demandais à quoi ca correspondait ?

    Merci
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  2. #2
    Membre habitué
    SAlut! ++i veut juste dire que la valeur de i est incrémenté avant son utilisation et i++ se sert d'abord de la valeur de i puis l'incrément ensuite. j'espère avoir pu répondre clairement . bonne suite
    Mes tutoriels sur Developpez.com : http://eric-gbofu.developpez.com
    Auteur du livre "Codename One – Développer en Java pour iOS, Android, BlackBerry et Windows Phone"
    Mon site sur la création de jeux vidéo : http://www.devjeux.com

  3. #3
    Rédacteur

    Un petit exemple:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int i:
       i = 12; printf("i=%d\n", ++i); // affiche 13
       i = 12; printf("i=%d\n", i++); // affiche 12
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  4. #4
    Modérateur

    Ce message n'a pas pu être affiché car il comporte des erreurs.

  5. #5
    Expert éminent
    Citation Envoyé par Obsidian Voir le message
    Sur des types natifs, l'impact est négligeable, mais sur des objets plus sophistiqués, les gains en performances peuvent être spectaculaires en remplaçant simplement i++ par ++i.
    Est-ce que tu as un benchmark montrant la nature spectaculaire des gains en performance? (Dans mon micro bench à moi, je les trouve tout sauf spectaculaires, plutôt difficile à mesurer de manière fiable).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  6. #6
    Rédacteur

    Attention, on est dans un forum C donc on essaye d'oublier les concepts applicables uniquement au c++.

    Je pense que Obsidian pensait à la différence de temps d'exécution entre le pre++ et le post++ (ou --, je suis pas sectaire) en C++. Le post++ demande la construction et aussi la destruction d'un objet temporaire.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  7. #7
    Expert éminent
    Citation Envoyé par ram-0000 Voir le message
    Attention, on est dans un forum C donc on essaye d'oublier les concepts applicables uniquement au c++.
    Oops.

    Je pense que Obsidian pensait à la différence de temps d'exécution entre le pre++ et le post++ (ou --, je suis pas sectaire) en C++. Le post++ demande la construction et aussi la destruction d'un objet temporaire.
    C'est bien ce que j'ai -- et d'autres -- ont tenté de mesurer dans des benchmarks. Rien de concluant à ma connaissance.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  8. #8
    Expert éminent sénior
    Citation Envoyé par Aspic Voir le message
    Bonjour,

    Je me lance dans la programmation C et je sais que pour incrémenter une variable, on utilise i++ mais en parcourant le net, j'ai vu une autre syntaxe bizarre ++i et je me demandais à quoi ca correspondait ?

    Merci
    Utilisé tout seul (comme il se doit), c'est strictement pareil.
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
     
    i++;
    ++i;

    ou dans un for().

    Ca devient tordu dans une expression. C'est tellement illisible et sujet au comportement indéterminée, que j'en déconseille l'usage dans ces conditions.

    Peu de gens dans le monde sont capable de dire si i = ++i; est déterminé ou non...
    Pas de Wi-Fi à la maison : CPL

  9. #9
    Expert éminent
    Citation Envoyé par Emmanuel Delahaye Voir le message
    Peu de gens dans le monde sont capable de dire si i = ++i; est déterminé ou non...
    Ce cas la est simple, c'est indefini (i est modifie deux fois sans point de sequencement entre les deux modifications).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  10. #10

  11. #11
    Expert éminent sénior
    Citation Envoyé par Emmanuel Delahaye Voir le message
    Utilisé tout seul (comme il se doit), c'est strictement pareil.
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
     
    i++;
    ++i;

    ou dans un for().

    Ca devient tordu dans une expression. C'est tellement illisible et sujet au comportement indéterminée, que j'en déconseille l'usage dans ces conditions.

    Peu de gens dans le monde sont capable de dire si i = ++i; est déterminé ou non...
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Ce cas la est simple, c'est indefini (i est modifie deux fois sans point de sequencement entre les deux modifications).
    Je suis 100% d'accord avec Emmanuel.

    Il est tordu, et très peu lisible, de se servir de la pré-incrémentation.

    Même si c'est autorisé, la lisibilité perd un tel facteur (d'autant plus que quand on trouve cela dans un code, ce n'est malheureusement pas le seul "shortcut" qui est mis), que cela amène tout droit à de l'obfuscation.

    Comme l'a dit Obsidian, ce n'est pas repris par beaucoup de langages, et il ne faut pas s'en étonner.

    Personellement, je déconseille fortement l'usage de la pré-incrémentation.
    "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

  12. #12
    Modérateur

    Citation Envoyé par Emmanuel Delahaye Voir le message
    Peu de gens dans le monde sont capable de dire si i = ++i; est déterminé ou non...
    Personnellement - et il doit encore me manquer quelque chose (on est là, entre autre, pour apprendre de ses erreurs) -, je ne trouve pas ça plus ambigü que i = i++.

    De prime abord, j'aurais même pensé que les opérateurs de pré-incrémentation et post-incrémentation étaient tous deux largement prioritaires sur =, et que la valeur de l'opérande de droite avait besoin d'être évaluée avant affectation, ne serait-ce que pour l'auto-référence style i = i + 1 puisse fonctionner. Dans ce sens, on devrait obtenir la valeur initiale de i, laquelle variable serait ensuite incrémentée implicitement, puis cette valeur initiale serait réaffectée à i, mais gcc n'est pas d'accord.

  13. #13
    Expert éminent sénior
    Citation Envoyé par Obsidian Voir le message
    <...>mais gcc n'est pas d'accord.
    En fait, et comme Jean Marc l'a rappelé, le comportement est indéterminé.
    gcc fait donc ce qu'il veut. Il aurait aussi bien pu rebooter ton PC ou envoyer à ta mère les photos de toi dansant nu sur la table de la cantine du lycée ...
    Pas de Wi-Fi à la maison : CPL

  14. #14
    Expert éminent
    Citation Envoyé par Obsidian Voir le message
    Personnellement - et il doit encore me manquer quelque chose (on est là, entre autre, pour apprendre de ses erreurs) -, je ne trouve pas ça plus ambigü que i = i++.
    Les deux ont un comportement indefini: i est modifie deux fois sans point de sequencement entre les modifications. L'objectif profond de la regle n'est pas de simplifier le compilateur dans des cas aussi simples. C'est de permettre au compilateur de supposer i != j dans des cas comme a[i] = a[j]++.

    Les priorites donnent un ordre partiel dans l'evaluation mais n'indiquent pas quand l'effet de bord des operateurs ++ et -- ou meme = a lieu. Le comportement est aussi indefini pour i = (i = 4) + 1, l'evaluation de i=4 (qui a pour resultat 4) a bien lieu avant la deuxieme assignation a i, mais cette contrainte n'existe pas pour l'effet de bord "modification de la valeur de i".
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  15. #15
    Modérateur

    Citation Envoyé par Emmanuel Delahaye Voir le message
    Il aurait aussi bien pu rebooter ton PC ou envoyer à ta mère les photos de toi dansant nu sur la table de la cantine du lycée ...

    Non à la pub sur l'alcool sur les sites web.
    Effectivement ! :-)

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Les priorites donnent un ordre partiel dans l'evaluation mais n'indiquent pas quand l'effet de bord des operateurs ++ et -- ou meme = a lieu.
    En effet, tout est là dedans, et ça paraît effectivement évident une fois qu'on le sait. :-) Merci.

  16. #16
    Expert éminent
    Citation Envoyé par Obsidian Voir le message
    En effet, tout est là dedans, et ça paraît effectivement évident une fois qu'on le sait. :-) Merci.
    En passant, il ne s'agit pas d'une simple indetermination de l'ordre comme dans f(g(), h()); ou on sait que soit g() est appele avant h() soit h() avant g() mais qu'il n'y a pas de recouvrement. Dans
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    long long t[1];
    size_t i =0, j = 0;
    t[i] = ( t[j] = 0xFFFFFFFFLL) + 1LL;

    on pourrait se retrouver vraisemblablement avec t[0] qui vaut 0 sur une machine 32 bits parce que les assignations peuvent se recouvrir (partie haute de t[i], partie haute de t[j], partie basse de t[j], partie haute de t[i]).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  17. #17
    Membre expert
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Les deux ont un comportement indefini: i est modifie deux fois sans point de sequencement entre les modifications. L'objectif profond de la regle n'est pas de simplifier le compilateur dans des cas aussi simples. C'est de permettre au compilateur de supposer i != j dans des cas comme a[i] = a[j]++.

    Les priorites donnent un ordre partiel dans l'evaluation mais n'indiquent pas quand l'effet de bord des operateurs ++ et -- ou meme = a lieu. Le comportement est aussi indefini pour i = (i = 4) + 1, l'evaluation de i=4 (qui a pour resultat 4) a bien lieu avant la deuxieme assignation a i, mais cette contrainte n'existe pas pour l'effet de bord "modification de la valeur de i".
    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
     
    #include <stdio.h>
     
    void call(int a, int b, int c, int d)
    {
    	printf("%d %d %d %d ",a,b,c,d) ;
    }
     
    int main(int argc, char **argv)
    {
    	int	i = 0 ;
     
    	call(i++, i++, ++i, ++i) ;
    	printf("%d\n", i) ;
     
    	i = 0 ;
            call(++i, ++i, i++, i++) ;
            printf("%d\n", i) ;
     
    	return 0 ;
    }


    à compiler avec différents compilateurs, différentes options d'optimisation, sur différents CPU, …

    et comparer avec
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
     
    volatile int i = 0 ;


    … surprises garanties…

  18. #18
    Expert éminent sénior
    Ça me rappelle la longue discussion avec doccpu.
    Si ça intéresse, j'ai toujours les MPs qu'on s'est échangés ensuite pour clore le débat...
    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.

  19. #19
    Candidat au Club
    Pour parler du comportement indéfini.
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Les deux ont un comportement indefini: i est modifie deux fois sans point de sequencement entre les modifications. L'objectif profond de la regle n'est pas de simplifier le compilateur dans des cas aussi simples. C'est de permettre au compilateur de supposer i != j dans des cas comme a[i] = a[j]++.

    Les priorites donnent un ordre partiel dans l'evaluation mais n'indiquent pas quand l'effet de bord des operateurs ++ et -- ou meme = a lieu. Le comportement est aussi indefini pour i = (i = 4) + 1, l'evaluation de i=4 (qui a pour resultat 4) a bien lieu avant la deuxieme assignation a i, mais cette contrainte n'existe pas pour l'effet de bord "modification de la valeur de i".
    Le comportement indéfini refuse que dans une même expression l'état interne d'un objet soit modifié doublement ...
    Exemple
    J'ai le code int a =0; int b = ++a + ++a;
    Valeur de b?