Qu'est-ce qui rend les développeurs C si curieux si «i ++ == ++ i»? [fermé]

15

Juste une observation aléatoire, il semble que sur StackOverflow.com, on se demande si "++ i == i ++". Cette question est posée tout le temps, je pense que je l'ai vue posée environ 6 ou 7 fois au cours des 2 derniers mois.

Je me demande juste pourquoi les développeurs C s'y intéressent autant? Le même concept / question existe également pour les développeurs C # et Java, mais je pense que je n'ai vu qu'une seule question liée à C #.

Est-ce parce que de nombreux exemples utilisent ++ i? Est-ce parce qu'il existe un livre ou un tutoriel populaire? Est-ce parce que les développeurs C aiment juste entasser autant que possible dans une seule ligne pour «efficacité» / «performance» et rencontrent donc des constructions «étranges» en utilisant plus souvent l'opérateur ++?

Michael Stum
la source
23
(Pour moi en tant que développeur C #, i ++ et ++ i sont égaux. Je sais qu'ils ne le sont pas, mais si j'écris du code qui dépend de la différence, je préfère le refactoriser pour qu'il soit plus lisible et m'attendre à ce que le compilateur et JITter prennent soin mais en tant que développeur C #, je n'essaye pas de sauver un ou deux cycles d'horloge car je suis déjà relativement inefficace de toute façon)
Michael Stum
1
en tant que programmeurs en herbe, nous aimons jouer avec l'arithmétique, la logique et sommes curieux de savoir comment les choses fonctionnent. Je pense que c'est une grande raison pour laquelle nous, noobs, aimons ces questions. ce n'est peut-être pas une fonctionnalité révolutionnaire, mais c'est certainement intéressant! N'est-ce pas la raison pour laquelle nous sommes devenus programmeurs en premier lieu?!
Chani
2
Faites-vous littéralement référence à l'expression ++i == i++, ou plus généralement à la différence de sens entre ++iet i++?
Keith Thompson

Réponses:

30

Je soupçonne qu'au moins une partie est un peu plus simple: même maintenant, nous voyons beaucoup de questions comme celle-ci commencer vers le début de l'année scolaire, et elles diminuent progressivement tout au long de l'année.

En tant que tel, je pense qu'il est juste de supposer que bon nombre d'entre eux sont simplement le résultat de cours dans lesquels l'enseignant en parle au moins un peu, mais n'explique pas très bien ses points (aussi souvent qu'autrement). parce qu'il ne les comprend pas vraiment lui-même). Particulièrement sur la base des personnes qui semblent poser ces questions, peu sont basées sur un codage réel.

Jerry Coffin
la source
14
N'est-ce pas l' opposé de septembre éternel? Septembre éternel était quand AOL a commencé à offrir l'accès Usenet à leurs clients, ce qui donne l'impression que septembre (le mois où les nouveaux élèves entrant à l'école ont traditionnellement bombardé les planches en tant que débutants) toute l'année.
nlawalker
C'est une théorie intéressante mais ce n'est peut-être pas toujours la faute des enseignants si quelqu'un ne comprend pas le matériel: peut-être que les élèves (1) ne faisaient pas assez attention pendant le cours et (2) trop paresseux pour chercher une réponse sur stackoverflow avant poser à nouveau la même question.
Giorgio
12

Parce que les programmeurs C doivent comprendre l'ordre des opérations. Les développeurs C # n'utilisent pas nécessairement les opérateurs au niveau du bit (&, |, ~) ou les opérateurs de préfixe car nous sommes normalement plus préoccupés par d'autres choses. Cependant, ce que nous, les développeurs C #, ne réalisons pas, c'est que nous devons savoir ce que font les opérateurs que nous utilisons quotidiennement et comment les utiliser correctement. La plupart d'entre nous évitent simplement les endroits où cela peut poser problème.

Du haut de votre tête, quelle est la sortie de cet extrait?

    double x = 5.5;
    Console.WriteLine(x++);
    x = 5.5;
    Console.WriteLine(++x);

Je dirais qu'un bon nombre de développeurs C # chevronnés n'ont aucune idée de la sortie vers la console.

Nate Noonen
la source
3
+1. Connaître la différence entre les opérateurs d'incrémentation / décrémentation avant et après correction en vaut la peine pour des situations comme celle-ci.
Maulrus
4
Je vois un peu le point et je ne connais pas non plus la sortie (je pense que c'est 5.5 et 6.5, mais je ne suis pas sûr), et pour moi cela n'aurait pas d'importance car je le refactoriserais en x ++; Console.WriteLine (x); immédiatement. Je ne suis pas totalement ignorant cependant, je pense juste que c'est une grosse odeur de code avec une facilité d'utilisation nulle.
Michael Stum
9
La réponse à la question n'a rien à voir avec l'ordre des opérations ou la différence entre les incréments de préfixe et de postfixe. C'est une question de comportement défini et indéfini.
David Thornley
2
Je l'ai rencontré aujourd'hui. Quelque chose comme if (myList[i++] == item). Intelligent. Je l'ai trouvé à la recherche de la source d'une exception IndexOutOfRange ... En effet, très "intelligent".
rmac
7
Je pense que c'est 5.5 et 6.5, mais je ne l'ai jamais vu ++utilisé sur un flotteur auparavant, et je dois dire que cela ne semble pas très approprié. Les gens font ça? (Je préfère += 1)
Bart van Heukelom
8

Je pense que c'est évident. En C #, pour an int i, i++ == ++iest toujours faux tandis que ++i == i++c'est toujours vrai, de manière fiable, et tous ceux qui sont intéressés peuvent le découvrir facilement simplement en apprenant les règles de C # (ou en le faisant simplement fonctionner).

En C et C ++, en revanche, il est presque indéfini car cela dépend du compilateur, de l'environnement d'exécution, de la plate-forme, etc., donc c'est une question beaucoup plus difficile à répondre, donc beaucoup de gens la posent.

Timwi
la source
+1 - mais ce n'est pas vraiment une question plus difficile à répondre. "indéfini" est un mot. Toutes les choses "cela dépend de ..." sont des choses dont la plupart des gens ne s'inquiètent pas. Même si vous n'écrivez que pour une plate-forme particulière, vous devez utiliser les idiomes normaux pour la langue dans son ensemble, et la plupart des utilisations des opérateurs pré-incrémentation et post-incrémentation font partie de quelques idiomes courants.
Steve314
+1: Cela répond en fait à la question posée (c'est-à-dire que vous ne lisez pas entre les lignes).
Thomas Eding
7

C'est une question populaire parce que c'est une question piège. Ce n'est pas défini .

Le lien ci-dessus renvoie à une FAQ sur la page d'accueil de Bjarnes Stroustrup, qui répond spécifiquement à cette question et explique pourquoi cette construction n'est pas définie. Ce qu'il dit, c'est:

Fondamentalement, en C et C ++, si vous lisez deux fois une variable dans une expression où vous l'écrivez également, le résultat n'est pas défini.

Le fait que l'ordre d'évaluation ne soit pas défini est censé produire un code plus performant.

user16764
la source
5

Très probablement parce qu'en C, cela importe vraiment si vous écrivez i++ou ++ilorsque vous faites de l'arithmétique de pointeur. Là, augmenter iavant ou après une opération pourrait être crucial. Je vous donnerais un exemple mais la dernière fois que j'ai écrit C était il y a 10 ans ...

En C #, je n'ai jamais rencontré de situation qui m'obligerait à réfléchir i++ou ++iparce que AFAIK, pour les boucles for / while, cela n'a pas vraiment d'importance.

Mladen Prajdic
la source
3
il est toujours important de comprendre les différences en C # - ce n'est pas parce que vous semblez les utiliser uniquement pour les boucles for / each que c'est le seul endroit où vous les trouverez
STW
totalement vrai que.
Mladen Prajdic
3
Ce n'est pas pertinent pour la question. La question n'est pas de la différence entre i++et ++i, mais de les combiner dans la même expression.
David Thornley
@David La question est de savoir pourquoi les programmeurs C sont curieux à ce sujet. La réponse (cela importe en C, pas tellement en C #) est tout à fait pertinente ".
Florian F
2

Il y a quelques années, j'ai lu que ces opérateurs étaient considérés comme dangereux, alors j'ai essayé de creuser plus d'informations à ce sujet. Si stackoverflow avait été en place à ce moment-là, je l'aurais demandé là-bas.

Maintenant, c'est parce que certaines personnes tordues écrivent des boucles telles que

while( [something] )
{
  a[++j] = ++j;
}

Même maintenant, je ne suis pas trop sûr de ce qui va / devrait arriver, mais il est assez clair pour moi que plusieurs ++ [var] sur la même ligne demandent des ennuis.

Eric
la source
2
Les incréments ont un comportement indéfini dans le cadre d'une affectation dans C
tzenes
7
Des affectations comme celles-ci x = ++j;sont bien définies en C. Ce qui précède n'est pas défini car il jest modifié deux fois sans points de séquence intermédiaires.
Matthew Flaschen
2

Deux raisons.

L'implémentation correcte de ++ i consiste à incrémenter i puis à le renvoyer. L'implémentation correcte d'i ++ consiste à enregistrer la valeur actuelle, à incrémenter i et à renvoyer la valeur enregistrée. Les connaître n'est pas implémenté car les synonymes sont importants.

La question devient alors quand le compilateur les applique-t-il lors de l'évaluation d'une expression, telle que l'égalité.

Si le test d'égalité est fait en premier, alors les opérateurs pré et post-incrémentation, vous allez devoir écrire une logique différente que si le côté gauche (lhs) et le côté droit (rhs) sont évalués en premier, puis l'égalité.

Tout dépend de l'ordre des opérations, et cela affecte à son tour le code que l'on écrit. Et, sans surprise, toutes les langues ne sont pas d'accord.

La liste des tests de base permet aux développeurs de tester pour voir si leurs hypothèses sont correctes, ainsi que si l'implémentation réelle correspond aux spécifications du langage.

Cela peut avoir toutes sortes d'impact lorsque vous travaillez avec des pointeurs, des boucles ou que vous retournez des valeurs.

Walt Stoneburner
la source
5
Les tests de base à ce sujet seront trompeurs, car il s'agit d'un comportement non défini. Si cela fonctionne exactement comme vous vous y attendez cette fois, rien ne garantit que ce sera la prochaine fois.
David Thornley
Vous avez répondu à la mauvaise question. Vous devriez répondre aux raisons pour lesquelles les programmeurs C sont curieux.
Hugo
Votre deuxième para est de toute façon incorrect (avant C ++ 11, au moins): le comportement de ++iest d' utiliser la valeuri+1 et à un moment donné, peut-être avant ou après cela, mais avant le point de séquence suivant, incrémenteri .
MM
@MattMcNabb - Pouvez-vous m'indiquer une spécification pour cela, je serais curieux de savoir si les choses ont changé dans la mise en œuvre. À l'époque où C correspondait bien à l'assemblage PDP, le ++ i a injecté une instruction INC, tandis que la version du suffixe devait copier la valeur dans un registre pour utiliser une instruction après l'incrément. Qu'est-ce qui a rendu nécessaire le changement que vous avez décrit?
Walt Stoneburner
2

Je pense que c'est un choc culturel.

Comme déjà souligné, le comportement d'une expression en C ou C ++ peut être indéfini car l'ordre d'exécution des post-incréments, etc. n'est pas strictement défini. Le comportement indéfini est assez courant en C, et bien sûr une grande partie de cela a été importé en C ++.

Pour quelqu'un qui a fait de la programmation dans un autre langage - quelqu'un qui a compris que les langages de programmation sont censés être précis et que les ordinateurs sont censés faire ce qu'on leur dit de faire ... eh bien, c'est un choc pour découvrir que C est intentionnellement vague sur certaines choses.

Steve314
la source
C est ainsi parce qu'il a été conçu pour prendre en charge beaucoup plus de plates-formes qu'il n'en existait même lorsque C # a été défini, y compris les plates-formes intégrées ou mainframe les plus étranges auxquelles vous puissiez penser. C #, d'autre part, fonctionne sur ... x86 et 360? peut-être ARM aussi? Rien d'autre. C'est pourquoi C # peut définir beaucoup plus.
DeadMG
++ De plus, C n'a-t-il pas d'abord été construit sur un PDP-11? Où il y avait des instructions d'incrémentation automatique? C voulait être "près de la machine" pour pouvoir utiliser utilement le jeu d'instructions.
Mike Dunlavey
@MikeDunlavey: Non, les C ++et les --opérateurs n'étaient pas basés sur le PDP-11, qui n'existait pas lorsque ces opérateurs ont été introduits dans le langage prédécesseur de C. B. Voir cm.bell-labs.com/who/dmr/chist.html et recherchez "auto-incrément".
Keith Thompson
1

C'est peut-être juste que les développeurs C utilisent l'incrémentation ++ plus souvent en général - vu que C n'a pas de "foreach" ou instruction similaire pour parcourir les tableaux. Oh, et bien sûr pointeur arithmatique, comme mentionné précédemment!

Robert Roos
la source
1
Bon point, j'ai oublié que foreach est un concept relativement moderne.
Michael Stum
-1

La différence entre les deux parties: le post et le pré-incrément fonctionnent comme ces deux morceaux de code devraient fonctionner dans toutes les langues. CE N'EST PAS DÉPENDANT DE LA LANGUE !!!

++i

C'est pré incrément. Ce morceau de code augmentera d'abord la valeur de iavant d'envoyer la valeur à la ligne où il est utilisé.

i++

Ceci est l'incrément de post. Ce morceau de code renverra la valeur de iavant d'augmenter la valeur de isur la ligne où il est utilisé.

Dans un autre petit exemple:

int main(void)
{
  int i = 0; 
  int result; 
  result = 10 + ++i; 
  printf("%d \n", result); // = 11 

  int j = 0; 
  result = 10 + j++; 
  printf("%d \n", result);// = 10
  return 0;
}

Ce code se compile avec les résultats sur le codepad.

Cela a à voir avec la mise en œuvre interne de la surcharge de l'opérateur.

++i augmente directement la valeur (et est donc un peu plus rapide)

i++crée d'abord une copie qui est retournée à l'endroit où cela est nécessaire et ensuite la valeur d'origine de la ivariable est augmentée d'une unité.

J'espère que c'est clair maintenant.

Krie999
la source
Pourtant, cela ne répond pas à la question réelle: pourquoi les développeurs C demandent-ils plus à ce sujet que les autres. L'OP comprend les opérateurs.
Martijn Pieters du
Cette réponse est également factuellement incorrecte. ++in'est pas plus rapide et i++ne crée pas de copie. De plus, ++ise comporte légèrement différemment en C qu'en C ++, et encore moins entre les autres langages.
MM