Was bedeutet ++ wirklich?

7

Die Frage wurde oft gestellt: "Was ist der Unterschied zwischen i ++ und ++ i"? Die akzeptierte Antwort bei Was ist der Unterschied zwischen i ++ und ++ i? , und ich habe diese Sprache auch an vielen anderen Orten gesehen, ist das, "i ++ bedeutet" sag mir den Wert von i, dann inkrementiere ", während ++ i" inkrementiere ich, dann sag mir den Wert '.

Was mich verwirrt, ist, dass mir nicht bewusst war, dass wir darüber diskutierten, einen Wert für ein entweder -Szenario zurückzubekommen. Ich dachte, dass i ++ syntaktisch äquivalent ist zu:

%Vor%

was eine Aussage ist, kein Ausdruck, also verstehe ich nicht, wo ich überhaupt zurückgegeben werde.

Können Sie bitte erklären, was die Aussage eigentlich bedeutet?

Danke,

    
as9876 12.10.2015, 00:09
quelle

3 Antworten

11

Bearbeiten: Siehe Erics Antwort , meine ist meh .

Sie haben Recht. % Co_de% entspricht ++ , aber der Punkt, den Sie sich merken sollten, ist, dass i = i + 1 nicht nur eine Anweisung ist, sondern auch als Ausdruck verwendet werden kann:

%Vor%

Also einfach zu schließen:

%Vor%     
SimpleVar 12.10.2015, 00:12
quelle
16

Aus unbekannten Gründen erhält diese alte Frage mit einer akzeptierten Antwort heute neue Antworten, von denen viele erhebliche Fehler oder Auslassungen enthalten. Lassen Sie mich versuchen, die Frage definitiv zu beantworten .

  

Die Frage wurde oft gestellt: "Was ist der Unterschied zwischen i ++ und ++ i"? Die akzeptierte Antwort bei [...], und ich habe diese Sprache auch an vielen anderen Orten gesehen, ist, dass "i ++" mir den Wert von i sagt, dann inkrementiere ", während ++ i" inkrementieren "bedeutet , dann sag mir den Wert '.

Wie ich in meiner Antwort auf die gleiche Frage festgestellt habe: Diese Charakterisierung ist üblich und ein vernünftiger erster Schritt zum Verständnis, aber leider irreführend, wenn Sie die Semantik sorgfältiger betrachten. Bitte lassen Sie sich durch diese vage und nicht ganz zutreffende Charakterisierung nicht irreführen. Lies stattdessen meine Antwort auf diese Frage.

  

Was mich verwirrt, ist, dass mir nicht bewusst war, dass wir in beiden Szenarien einen Wert für i zurückbekamen. Ich dachte, dass i++ syntaktisch äquivalent zu i = i + 1; ist, was eine Aussage ist, kein Ausdruck, also verstehe ich nicht, wo ich überhaupt zurückgegeben werde.

Sie haben hier eine Reihe von Missverständnissen. Anstatt sie alle anzugreifen, wollen wir nur sagen, was die Wahrheit ist.

Erstens sind ++i und i++ nicht syntaktisch genau äquivalent zu irgendetwas . Sie können nicht notwendigerweise ein rechtliches Programm nehmen, das ein ++i oder ein i++ enthält und es nur syntaktisch in ein anderes rechtliches Programm transformieren. Also verbanne diesen Gedanken einfach von deinem Kopf. Diese sind moralisch äquivalent zu increment-and-assign und sollten semantisch äquivalent sein, aber es gibt nicht notwendigerweise eine syntaktische Entschlüsselung, die das Programm bewahrt Semantik oder Legalität.

Sagen wir jetzt noch mehr wahre Dinge. Aber zuerst einige Vorbehalte. Für die Zwecke dieser Diskussion ist der inkrementierte Ausdruck i eine Variable vom Typ int, die entweder als eine Variable oder ein Wert ohne Nebenwirkungen, einschließlich Ausnahmen, ausgewertet werden kann. Außerdem nehmen wir an, dass die Inkrementierungsoperation keine Ausnahme erzeugt. Und außerdem nehmen wir einen einzigen Ausführungsstrang an. Wenn Sie die Semantik von Inkrementen und Zuweisungen in Fällen kennen möchten, in denen das Auswerten der Variablen einen anderen Nebeneffekt erzeugen kann oder keine Variable ist, sondern eine Eigenschaft ist oder die Operationen benutzerdefiniert sind oder mehrere Threads beobachten oder ändern Sie die Variable, siehe die Spezifikation für Details .

Das heißt, hier sind ein paar Fakten:

  • ++i , i++ und i = i + 1 sind Ausdrücke
  • ++i; , i++; und i = i + 1; sind Anweisungen
  • Die Semantik von ++i lautet wie folgt:

    1. temp1 erhält den Wert von i
    2. temp2 erhält den Wert von temp1 + 1
    3. i hat den Wert von temp2
    4. Der Wert des Ausdrucks ist temp2
  • Die Semantik von i++ lautet wie folgt:

    1. temp1 erhält den Wert von i
    2. temp2 erhält den Wert von temp1 + 1
    3. i hat den Wert von temp2
    4. Der Wert des Ausdrucks ist temp1
  • Beachten Sie, dass der Unterschied zwischen den beiden Formen nur ist, was der erzeugte Wert ist. Die Schritte, die zur Erzeugung des Nebeneffekts unternommen werden, sind in beiden Fällen identisch. Sie sind garantiert in single-threaded C #, dass der Nebeneffekt vollständig beobachtet wird, bevor der Wert erzeugt wird.

  • Die Semantik von i = i + 1 lautet wie folgt:
    1. temp1 erhält den Wert von i
    2. temp2 erhält den Wert von temp1 + 1
    3. i hat den Wert von temp2
    4. Der Wert des Ausdrucks ist temp2
  • Beachten Sie, dass die Semantik von i = i + 1 mit der Semantik von ++i identisch ist. Dies ist keine Garantie, dass Sie in einem beliebigen Programm i = i + 1 für ++i oder umgekehrt syntaktisch ersetzen können. In bestimmten Programmen könnte dies möglich sein.
  • Beachten Sie, dass die Semantik von i++ keine "einfache" semantisch äquivalente Form zulässt. ((Func<int, int, int>)((int j, int k)=>j))(i, i=i+1) hat dieselbe Semantik, ist aber offensichtlich eine verrückte Sache.

  • Die Semantik der Anweisungsformen aller drei ist:

    1. Bewerten Sie den Ausdruck als normal.
    2. Verwerfe das Ergebnis.

Hoffentlich klärt das definitiv alle Missverständnisse darüber auf, was ein Ausdruck ist, was eine Aussage ist, welche Nebenwirkungen und Werte die Ausdrücke erzeugen und in welcher Reihenfolge sie geschehen. Beachten Sie, dass diese Erklärung nur für einfache Fälle mit ganzzahligen Variablen ohne Nebenwirkungen auf einen einzelnen Thread gedacht ist.Weitere Informationen dazu, wie diese Operationen mit anderen Typen funktionieren oder mit Ausnahmen interagieren oder wie sie in Multithread-Programmen funktionieren, finden Sie in der C # -Spezifikation oder stellen Sie eine spezifischere Frage.

Schließlich: Ich persönlich finde das immer noch verwirrend, und ich programmiere seit 30 Jahren in C-Nachkommensprachen und implementiere diese Semantik in C #. Wenn ich sie verwirrend finde, und wenn fast jede Antwort auf jede Frage, die ich auf diesen Operatoren sehe, signifikante Fehler oder Auslassungen enthält, dann können wir sicher schließen, dass dies verwirrende Operatoren sind. Daher verwende ich fast nie ++ oder -- in meinem Produktionscode. Ich denke, es ist ein schlechter Stil, einen Ausdruck zu haben, der sowohl für seinen Wert als auch für seine Nebenwirkungen nützlich ist.

Versuchen Sie, eine Möglichkeit zu finden, Ihr Programm so zu strukturieren, dass jede Aussage eine Nebenwirkung hat und Nebeneffekte auf Ausdrucksanweisungen beschränkt sind. Vermeiden Sie ++ und vermeiden Sie insbesondere jedes Szenario, in dem i++ und ++i unterschiedliche Semantiken hätten, weil das ein Punkt ist, an dem das Programm schwerer zu verstehen und daher schwieriger zu verwalten ist.

    
Eric Lippert 21.01.2018 18:07
quelle
0

Ich denke, Sie können die folgenden zwei Funktionen betrachten, um eine Analogie zu i++ und ++i zu erhalten.

Geige

%Vor%

Genau wie Funktionsaufrufe sind i++ und ++i rechte Ausdrücke , dh var a = i++; und var a = ++i; sind gültige Anweisungen. Aber i++ = 5; und ++i = 5; sind nicht gültig, da dies als linksseitige Ausdrücke verwendet werden würde.

    
nl-x 21.01.2018 16:12
quelle

Tags und Links