Il n'est pas défini car il modifie x
deux fois entre les points de séquence. La norme dit qu'elle n'est pas définie, donc elle n'est pas définie.
Ça, je le sais.
Mais pourquoi?
Ma compréhension est que l'interdire permet aux compilateurs de mieux optimiser. Cela aurait pu avoir un sens lorsque C a été inventé, mais semble maintenant être un argument faible.
Si nous devions réinventer C aujourd'hui, le ferions-nous de cette façon, ou peut-on faire mieux?
Ou peut-être y a-t-il un problème plus profond, qui rend difficile la définition de règles cohérentes pour de telles expressions, il est donc préférable de les interdire?
Supposons donc que nous devions réinventer C aujourd'hui. Je voudrais suggérer des règles simples pour des expressions telles que x=x++
, qui me semblent mieux fonctionner que les règles existantes.
J'aimerais avoir votre avis sur les règles suggérées par rapport aux règles existantes, ou d'autres suggestions.
Règles suggérées:
- Entre les points de séquence, l'ordre d'évaluation n'est pas spécifié.
- Les effets secondaires se produisent immédiatement.
Aucun comportement indéfini n'est impliqué. Les expressions correspondent à cette valeur ou à cela, mais ne formateront sûrement pas votre disque dur (étrangement, je n'ai jamais vu d'implémentation où x=x++
formate le disque dur).
Exemples d'expressions
x=x++
- Bien défini, ne change pasx
.
Tout d'abord,x
est incrémenté (immédiatement lorsqu'ilx++
est évalué), puis son ancienne valeur est stockée dansx
.x++ + ++x
- Incrémentex
deux fois, évalue à2*x+2
.
Bien que chaque côté puisse être évalué en premier, le résultat est soitx + (x+2)
(côté gauche en premier) ou(x+1) + (x+1)
(côté droit en premier).x = x + (x=3)
- Non spécifié,x
défini surx+3
ou6
.
Si le côté droit est évalué en premier, c'est le casx+3
. Il est également possible que lex=3
premier soit évalué, donc c'est le cas3+3
. Dans les deux cas, l'x=3
affectation se produit immédiatement lorsqu'ellex=3
est évaluée, de sorte que la valeur stockée est remplacée par l'autre affectation.x+=(x=3)
- Bien défini, définix
sur 6.
Vous pourriez dire que ce n'est qu'un raccourci pour l'expression ci-dessus.
Mais je dirais que cela+=
doit être exécuté aprèsx=3
, et non en deux parties (lirex
, évaluerx=3
, ajouter et stocker une nouvelle valeur).
Quel est l'avantage?
Certains commentaires ont soulevé ce bon point.
Je ne pense certainement pas que des expressions telles que celles qui x=x++
devraient être utilisées dans un code normal.
En fait, je suis beaucoup plus strict que cela - je pense que le seul bon usage pour x++
en tant que x++;
seul.
Cependant, je pense que les règles linguistiques doivent être aussi simples que possible. Sinon, les programmeurs ne les comprennent tout simplement pas. la règle interdisant de changer une variable deux fois entre des points de séquence est certainement une règle que la plupart des programmeurs ne comprennent pas.
Une règle très basique est la suivante:
si A est valide, et B est valide, et qu'ils sont combinés de manière valide, le résultat est valide.
x
est une valeur L valide, x++
est une expression valide et =
est un moyen valide de combiner une valeur L et une expression, alors comment se x=x++
fait-il que ce ne soit pas légal?
La norme C fait ici une exception, et cette exception complique les règles. Vous pouvez rechercher stackoverflow.com et voir à quel point cette exception déroute les gens.
Alors je dis - débarrassez-vous de cette confusion.
=== Résumé des réponses ===
Pourquoi faire ça?
J'ai essayé d'expliquer dans la section ci-dessus - je veux que les règles C soient simples.Potentiel d'optimisation:
cela prend une certaine liberté du compilateur, mais je n'ai rien vu qui m'a convaincu qu'il pourrait être significatif.
La plupart des optimisations peuvent encore être effectuées. Par exemple,a=3;b=5;
peut être réorganisé, même si la norme spécifie l'ordre. Des expressions telles quea=b[i++]
peuvent encore être optimisées de la même manière.Vous ne pouvez pas modifier la norme existante.
J'avoue, je ne peux pas. Je n'ai jamais pensé pouvoir réellement aller de l'avant et changer les normes et les compilateurs. Je voulais seulement penser si les choses auraient pu être faites différemment.
x
à lui-même, et si vous voulez augmenter,x
vous pouvez simplement direx++;
- pas besoin de l’affectation. Je dirais que cela ne devrait pas être défini simplement parce qu'il serait difficile de se rappeler ce qui est censé se produire.