2009-10-02 7 views
26

Halb scherzhaft halb ernst : Warum kann ich nicht ++i++ in C-ähnlichen Sprachen, speziell in C# tun?Warum kann ich ++ i ++ in C-ähnlichen Sprachen nicht tun?

Ich würde erwarten, dass es den Wert inkrementieren, verwenden Sie das in meinem Ausdruck und dann wieder inkrementieren.

+37

Auch wenn es funktioniert hat, sollten Sie nicht, weil Sie nicht das Leben hassen sollte: (. Sehen ++ i ++ würde ich traurig in jedem Kontext machen, unabhängig von der Erklärung. – Malaxeur

+0

kann nicht, und sollte nicht. – luke

+1

ich wusste nicht, es war der „dumme-Operator-Trick“ Tag dank John! – zvolkov

Antwort

57

Kurze Antwort: i++ ist kein "Lvalue", also kann nicht Gegenstand einer Aufgabe sein.

+3

post-increment hat Vorrang vor pre-increment; Sie wollen sagen, dass 'i ++' kein lvalue ist, nicht '++ i'. (Auch wenn es nicht so oder so funktioniert) –

+13

'++ I' ist ein L-Wert, so' (++ i) ++ 'würde gültig sein, aber die Tatsache, dass es schreibt' I' zweimal ohne eine dazwischenliegende Sequenz Punkt . Das Problem ist, dass die Grammatik angibt, dass '++ i ++' äquivalent zu '++ (i ++) 'ist. –

+0

@Charles Bailey: ++ i ist ein Lvalue in C und C++, aber IIRC nicht in C#. –

18

Weil Sie sich Gedanken über einen nächsten Programmierer machen, der Ihren Code beibehält (oder versucht, ihn neu zu schreiben), lange nachdem Sie gefeuert wurden, um populären Konventionen zu trotzen.

+2

Aus diesem Grunde ist es‚unmoralisch‘, aber in Wirklichkeit ist es illegal und unmoralisch. –

+3

leider viele C++ (hoffentlich in dem nächsten Standard festgelegt wird) sind unmoralisch und politisch nicht korrekt zu verwenden, dennoch legal ... – vehomzzz

+0

, dass ein Kommentar zu dem Entwurf eines EU-Programms ist, mehr als eine Sprache für die Planung. .. – DanM

3

Ich glaube, dass der Inkrement (oder Dekrement) -Operator benötigt einen Lvalue zuzuweisen. Jedoch ist ++ kein Wert, es ist ein Ausdruck. Jemand, der mit Compilern besser vertraut ist, könnte möglicherweise klären, ob es einen technischen Grund für diese Einschränkung gibt.

+1

Der Typ von ++ i * ist * ein lvalue in C. –

+0

Könnten Sie das ein bisschen klären? Ich habe versucht, "++ i = 4;" und erhalten einen Fehler, der besagt, dass ein Lvalue auf der linken Seite des Operanden erforderlich ist. Vielleicht liegt mein Missverständnis in der Definition von Lvalue? Ich verstand es als etwas, das man zuordnen konnte. – nall

+3

Abschnitt 5.3.2 der Norm, Absatz 1: "Der Wert ist der neue Wert des Operanden; es ist ein Lvalue." (Dies ist natürlich der Absatz auf "Präfix ++".) Natürlich, "++ i = 4;" ist auch ein Versuch, den Wert von i zweimal ohne einen dazwischenliegenden Sequenzpunkt und daher undefiniertes Verhalten zu ändern. "f (++ i)" mit "int f (int &)" würde einen Sequenzpunkt beinhalten und sollte legal sein. –

6

Da das Ergebnis von i++ kein Lvalue ist.

+0

++ ich würde zuerst ausgewertet werden. –

+6

Post-Inkrement hat tatsächlich Vorrang. –

3

Aus dem Bereich 7.5.9 der C# 3.0 specification:

Der Operand einer Postfix Erhöhung oder Dekrementoperation muss ein Ausdruck als Variable klassifiziert werden, ein Eigenschaft Zugang oder einen Indexer-Zugriff. Das Ergebnis der Operation ist ein Wert vom gleichen Typ wie der Operand. Wenn der Operand eines Postfixinkrements oder Dekrementoperation eine Eigenschaft oder Indexerzugriff ist, muss die Eigenschaft indexer sowohl einen get- als auch einen set- -Accessor haben. Wenn dies nicht der Fall ist, tritt ein Fehler bei der Kompilierung auf.

Zusätzlich kann die post-Inkrementausdruck (i++) würde zuerst ausgewertet werden, da sie eine höhere Priorität als der Prä-Inkrement (++i) Operator hat.

84

Obwohl die kurze Antwort "es ist kein lvalue" ist richtig, das ist vielleicht nur die Frage betteln. Warum ist es nicht ein lvalue? Oder, wie wir in C# sagen, eine Variable.

Der Grund ist, weil Sie nicht Ihren Kuchen haben und es auch essen können. Ermitteln Sie logisch:

Zunächst ist die Bedeutung eines ++ Operators in C#, ob Postfix oder Präfix, "nehmen Sie den Wert dieser Variablen, erhöhen Sie den Wert, weisen Sie der Variablen den neuen Wert zu einen Wert als Ergebnis erzeugen ". Der als Ergebnis erzeugte Wert ist entweder der ursprüngliche Wert oder der inkrementierte Wert, abhängig davon, ob es sich um ein Postfix oder ein Präfix handelte. Wie auch immer, Sie produzieren einen Wert.

Zweitens, der Wert einer Variablen ist immer der aktuelle Inhalt dieser Variablen. (Modulo bestimmte bizarre Threading-Szenarien, die uns weit weg bringen würde.)

Ich hoffe, Sie stimmen zu, dass dies vollkommen vernünftige Regeln sind.

Nun sollte es klar sein, warum das Ergebnis von i ++ keine Variable sein kann, aber im Fall, dass es nicht, lassen Sie mich klarstellen:

Angenommen i 10. Die Bedeutung von i sollte „get ++ seine der Wert von i - 10 - inkrementiere es - 11 - speichere es - i ist jetzt 11 - und gib den ursprünglichen Wert als Ergebnis - 10 "an. Also, wenn Sie print (i ++) sagen, sollte es 10 drucken, und 11 sollte in i gespeichert werden.

Nehmen wir nun an die Bedeutung von i ++ ist die Variable, nicht den Wert zurückzukehren. Du sagst print (i ++) und was passiert? Sie erhalten den Wert von i - 10 - erhöhen Sie es - 11 - speichern Sie es - ich bin jetzt 11 - und geben Sie die Variable als Ergebnis zurück. Was ist der aktuelle Wert der Variablen? 11! Welches ist genau das, was Sie NICHT drucken möchten.

Kurz gesagt, wenn i ++ eine Variable zurückgibt, dann würde es tun genau das Gegenteil der beabsichtigten Bedeutung des Betreibers! Ihr Vorschlag ist logisch inkonsistent, weshalb keine Sprache dies tut.

+1

Eigentlich sollte das Pre-Inkrement den Wert erhöhen und einen Verweis auf das ursprüngliche Objekt zurückgeben, nicht auf einen Wert. –

+3

Schöne Erklärung – peacedog

+4

Martin, meine Erklärung ist sowohl präzise als auch genau; Ich spreche von der C# -Semantik, nicht von der C- oder C++ - Semantik, denn genau darum hat das ursprüngliche Poster gebeten. Ich werde das im Text deutlicher machen. –

8

I getestet (++ i, i ++) als Behelfslösung:

#include <stdio.h> 

int main(){ 
    int i=0; 

    printf(" i:   %i\n", i  ); 
    printf(" (++i,i++): %i\n", (++i,i++)); 
    printf(" i:   %i\n", i  ); 
} 

Ergebnis:


i:   0 
(++i,i++): 1 
i:   2 
+8

Meine Augen, meine Augen! – RJFalconer

+0

+1 für Workaround, das die Symmetrie beibehält. – cobbal

+0

Sieht aus wie eine Art Emoticon. Die Spruce Goose fliegt kopfüber? –

Verwandte Themen