web-dev-qa-db-fra.com

Comportement des opérateurs avant et après incrémentation en C, C ++, Java et C #

AVERTISSEMENT: Ce n'est pas un exemple réel. C'est juste une question théorique sur le fonctionnement de ces langues.

Quelles sont exactement les différences entre C/C++, C # et Java en ce qui concerne les opérateurs de post et pré-incrémentation?

C'est ce que j'obtiens avec VC++ 10, Java 1.6 et C # 4

int a = 2;
int b = a++ + a++;
int c = ++a + a++ + a++;

      +-----+------+------+----+
      |  C  | C++  | Java | C# |
+-----+-----+------+------+----+
| a   |  7  |  7   |   7  |  7 |
+-----+-----+------+------+----+
| b   |  4  |  4   |   5  | 5  |
+-----+-----+------+------+----+
| c   | 15  |  15  |  16  | 16 |
+-----+-----+------+------+----+
57
Nick

Java et C # évaluent les expressions de gauche à droite, et les effets secondaires sont visibles immédiatement.

En C++, l'ordre d'évaluation des sous-expressions n'est pas spécifié, et la modification du même objet deux fois sans point de séquence intermédiaire est un comportement non défini.

63
fredoverflow

Je n'ai pas le temps de rédiger une description détaillée des différences entre C++, C, C # et Java. Je dirai simplement que le comportement C # des opérateurs pré et post-incrémentation est entièrement spécifié (dans les scénarios à thread unique; si vous voulez en savoir plus sur son atomicité, garanties sur les observations des ordres de lecture et d'écriture dans les modèles de mémoire faible multiprocesseurs et ainsi de suite, vous êtes seul à faire cette recherche.) Il n'est pas entièrement spécifié en C et C++; un compilateur a une grande latitude pour faire tout ce qu'il veut avec des effets secondaires de réorganisation. Je n'ai jamais utilisé Java donc je ne vais pas risquer de deviner ce que fait Java.

Pour plus d'informations sur ce que fait C #, vous devriez lire la spécification C #. Pour un bref aperçu, lisez ma réponse à cette question:

Quelle est la différence entre i ++ et ++ i?

Pour une prise encore plus courte:

Les sous-expressions dans une expression C # sont logiquement regroupées par priorité et associativité, puis évaluées de de gauche à droite indépendamment. (Ainsi, par exemple, A() + B() * C() évalue A (), puis B (), puis C (). Le fait que la multiplication "précède" l'addition est sans importance; les sous-expressions sont toujours évaluées de gauche à droite.)

Si l'évaluation d'une sous-expression provoque un effet secondaire en raison d'une sous-expression pré ou post-incrémentation, alors l'effet secondaire se produit juste avant le résultat est produit.

33
Eric Lippert

En C++, il s'agit d'un comportement non défini, donc toute réponse serait correcte. Voir Comportement indéfini et points de séquence pour plus de détails.

Je ne suis pas sûr des autres langues, mais je m'attendrais à ce que ce code soit incorrect là aussi.

ÉDITER:
Voir la réponse d'Eric Lippert à propos de C #. Il réfute mon hypothèse sur le comportement de C #.

4
Vlad

En C++ au moins ce comportement indéfini. Citant la norme C++:

Entre le point de séquence précédent et suivant, un objet scalaire doit voir sa valeur stockée modifiée au plus une fois par l'évaluation d'une expression.

4
GWW

J'aime cette question et j'ai trouvé de très bonnes explications mais je veux juste expliquer cette question par sa valeur comment elle est évaluée:

Je ne parlerai que de Java et c/C++ car je n'ai aucune connaissance de C #

Les déclarations sont évaluées de la manière suivante

En Java

Déclaration |||||||||||||||||||||||||||||||||||||||||||||| |||||||||| Trace

int a= 2;                     a=2
int b= a++ + a++;             a=2, a=3

here value of a=4

int c = ++a + a++ + a++;      a=5, a=5, a=6

here value of a=7

En C/C++

Trace de déclaration

int a= 2;                     a=2
int b= a++ + a++;             a=2, a=2

here value of a=4

int c = ++a + a++ + a++;      a=5, a=5, a=5

here value of a=7

En bref dans Java expression va de gauche à droite donc au 2ème "a" il va chercher une nouvelle valeur et en c/c ++ il va d'abord évaluer l'expression entière puis incrémenter tous les opérandes de l'instruction.

1
commit

Le modèle de mémoire Java assure l’ordre dans lequel les chargements et les magasins sont effectués, donc il devrait en être de même sur n’importe quelle machine virtuelle Java (je crois).

Il ressemble à C++ a le même ordre d'opérations , mais une fois que vous l'utilisez deux fois sur une ligne, vous commencez à exécuter d'autres choses (Vlad est là). Si vous essayez d'autres compilateurs C++, vous trouverez peut-être des réponses différentes.

Je suis sûr que C # a le même ordre d'opérations, mais je suppose qu'ils ont un modèle de mémoire (comme Java) qui garantit la cohérence, mais je n'ai pas beaucoup de connaissances ici.

1
MBCook