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 :

Différence entre ++i et i++


Sujet :

C

  1. #1
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut 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é Avatar de doderic
    Homme Profil pro
    Inscrit en
    Mai 2004
    Messages
    215
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 215
    Points : 165
    Points
    165
    Par défaut
    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

  3. #3
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    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
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 370
    Points : 23 625
    Points
    23 625
    Par défaut
    J'ajoute que les pré-incrémentation et pré-décrémentation existent en C depuis le début et que de nombreux langages parus depuis ne les implémentent pas, pour une raison que j'ignore.

    La possibilité de faire ce genre d'opération à l'avance se justifie tout autant que celle de la mener après coup, tant d'un point de vue technique qu'algorithmique. L'exemple-ambassadeur est celui de la gestion d'une pile, structure pour le moins répandue en informatique.

    - Lorsque l'on dépile, on renvoie l'objet repéré par l'index de la pile, puis on incrémente celui-ci. Donc :
    - Lorsque l'on empile, il faut d'abord décrémenter l'index, puis sauver l'objet à la place nouvellement indiquée. En C, ça donnerait :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typedef struct _pile { char tableau [TAILLE]; unsigned int index; } pile;
    
    char depile (pile * p)
    {
        return p->tableau[p->index++];
    }
    
    void empile (pile * p, char c) 
    {
        p->tableau[--(p->index)] = c;
    }

    Sans pré-décrémentation, tu serais obligé de faire l'opération d'empilement en deux étapes.

    L'utilité de ces opérateurs prennent tout leur sens en C++, dans lequel on peut définir des objets conséquents répondant à ces opérateurs. Dans le cast d'une post-(in|dé)crémentation, tu es obligé de créer une copie de l'objet actuel, de le mettre à jour et de renvoyer la copie (en prenant en compte son éventuelle destruction ultérieure). En revanche, en pré-(in|dé)crémentant, il te suffit de mettre l'objet à jour puis d'y faire référence, sans avoir quoi que ce soit à déplacer.

    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.

  5. #5
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    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

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    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

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    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
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    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.
    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

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    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
    Rédacteur

    Avatar de khayyam90
    Homme Profil pro
    Architecte de système d’information
    Inscrit en
    Janvier 2004
    Messages
    10 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Architecte de système d’information

    Informations forums :
    Inscription : Janvier 2004
    Messages : 10 369
    Points : 40 164
    Points
    40 164

  11. #11
    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 Emmanuel Delahaye Voir le message
    Utilisé tout seul (comme il se doit), c'est strictement pareil.
    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
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 370
    Points : 23 625
    Points
    23 625
    Par défaut
    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
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    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

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    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
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 370
    Points : 23 625
    Points
    23 625
    Par défaut
    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

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    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
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 937
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 937
    Points : 4 358
    Points
    4 358
    Par défaut
    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
    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
    Ç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
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Juillet 2012
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Juillet 2012
    Messages : 1
    Points : 2
    Points
    2
    Par défaut 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?

Discussions similaires

  1. Différence entre un "bidouilleur" et un Pro ?
    Par christ_mallet dans le forum Débats sur le développement - Le Best Of
    Réponses: 290
    Dernier message: 28/11/2011, 10h53
  2. Réponses: 5
    Dernier message: 11/12/2002, 12h31
  3. Différence entre TCP, UDP, ICMP
    Par GliGli dans le forum Développement
    Réponses: 1
    Dernier message: 13/09/2002, 08h25
  4. Différences entre jmp, jz, jnz, etc
    Par christbilale dans le forum Assembleur
    Réponses: 3
    Dernier message: 05/07/2002, 15h09
  5. Réponses: 3
    Dernier message: 07/05/2002, 16h06

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