Es ist undefiniert, da es x
zwischen Sequenzpunkten zweimal geändert wird. Der Standard sagt, es ist undefiniert, daher ist es undefiniert.
Soviel weiß ich.
Aber wieso?
Meines Wissens nach können Compiler besser optimieren, wenn dies untersagt wird. Dies hätte Sinn machen können, als C erfunden wurde, aber jetzt scheint es ein schwaches Argument zu sein.
Wenn wir C heute neu erfinden würden, würden wir es dann so machen, oder könnte es besser gemacht werden?
Oder gibt es ein tieferes Problem, das es schwierig macht, konsistente Regeln für solche Ausdrücke zu definieren, also ist es am besten, sie zu verbieten?
Nehmen wir also an, wir würden C heute neu erfinden. Ich möchte einfache Regeln für Ausdrücke wie vorschlagen x=x++
, die meiner Meinung nach besser funktionieren als die vorhandenen Regeln.
Ich würde gerne Ihre Meinung zu den vorgeschlagenen Regeln im Vergleich zu den vorhandenen oder zu anderen Vorschlägen einholen.
Vorgeschlagene Regeln:
- Zwischen den Sequenzpunkten ist die Reihenfolge der Auswertung nicht angegeben.
- Nebenwirkungen treten sofort auf.
Es ist kein undefiniertes Verhalten beteiligt. Ausdrücke werden auf diesen oder jenen Wert ausgewertet, formatieren Ihre Festplatte jedoch nicht (seltsamerweise habe ich noch nie eine Implementierung gesehen, bei der x=x++
die Festplatte formatiert wird).
Beispielausdrücke
x=x++
- Gut definiert, ändert sich nichtx
.
Zuerstx
wird inkrementiert (sofort, wennx++
ausgewertet wird), dann wird der alte Wert in gespeichertx
.x++ + ++x
- Inkrementiertx
zweimal, ergibt2*x+2
.
Obwohl jede Seite zuerst bewertet werden kann, ist das Ergebnis entwederx + (x+2)
(linke Seite zuerst) oder(x+1) + (x+1)
(rechte Seite zuerst).x = x + (x=3)
- Nicht angegeben,x
auf entwederx+3
oder eingestellt6
.
Wenn die rechte Seite zuerst ausgewertet wird, ist esx+3
. Es ist auch möglich, dassx=3
zuerst ausgewertet wird, also ist es3+3
. In beiden Fällen erfolgt diex=3
Zuweisung sofortx=3
nach der Auswertung, sodass der gespeicherte Wert durch die andere Zuweisung überschrieben wird.x+=(x=3)
- Gut definiert, setztx
auf 6.
Sie könnten argumentieren, dass dies nur eine Abkürzung für den obigen Ausdruck ist.
Aber ich würde sagen, das+=
muss nachher ausgeführtx=3
werden und nicht in zwei Teilen (lesenx
, auswertenx=3
, addieren und neuen Wert speichern).
Was ist der vorteil
Einige Kommentare haben diesen guten Punkt angesprochen.
Ich denke nicht, dass Ausdrücke, wie x=x++
sie in einem normalen Code verwendet werden sollten.
Eigentlich bin ich viel strenger als das - ich halte die einzig gute Verwendung für rein x++
wie x++;
alleine.
Ich denke jedoch, dass die Sprachregeln so einfach wie möglich sein müssen. Sonst verstehen sie die Programmierer einfach nicht. Die Regel, die das zweimalige Ändern einer Variablen zwischen Sequenzpunkten verbietet, ist sicherlich eine Regel, die die meisten Programmierer nicht verstehen.
Eine sehr grundlegende Regel lautet:
Wenn A gültig ist und B gültig ist und sie auf gültige Weise kombiniert werden, ist das Ergebnis gültig.
x
ist ein gültiger L-Wert, x++
ein gültiger Ausdruck und =
eine gültige Möglichkeit, einen L-Wert und einen Ausdruck zu kombinieren. Warum x=x++
ist das nicht zulässig?
Der C-Standard macht hier eine Ausnahme, und diese Ausnahme kompliziert die Regeln. Sie können stackoverflow.com durchsuchen und sehen, wie sehr diese Ausnahme die Menschen verwirrt.
Also sage ich - befreie dich von dieser Verwirrung.
=== Zusammenfassung der Antworten ===
Warum das tun?
Ich habe versucht, dies im obigen Abschnitt zu erklären - ich möchte, dass C-Regeln einfach sind.Optimierungspotential:
Dies nimmt dem Compiler zwar etwas Freiheit, aber ich habe nichts gesehen, was mich davon überzeugt hätte, dass es von Bedeutung sein könnte.
Die meisten Optimierungen können noch durchgeführt werden. Beispielsweisea=3;b=5;
kann nachbestellt werden, obwohl der Standard die Reihenfolge festlegt. Ausdrücke wiea=b[i++]
können noch ähnlich optimiert werden.Sie können den vorhandenen Standard nicht ändern.
Ich gebe zu, ich kann nicht. Ich hätte nie gedacht, dass ich tatsächlich Standards und Compiler ändern kann. Ich wollte nur darüber nachdenken, ob die Dinge anders hätten gemacht werden können.
x
sich selbst zuzuweisen , und wenn Sie inkrementieren möchten,x
können Sie einfach sagenx++;
- die Zuweisung ist nicht erforderlich. Ich würde sagen, es sollte nicht definiert werden, nur weil es schwierig ist, sich daran zu erinnern, was passieren soll.