Warum ist "++ i ++" ungültig, während (++ i) ++ gültig ist?

14

Betrachten wir den folgenden Code:

int main() {
    int i = 2;
    int b = ++i++;
    return 3;
}

Es wird mit folgendem Fehler kompiliert:

<source>: In function 'int main()':

<source>:3:16: error: lvalue required as increment operand

    3 |     int b = ++i++;

      |                ^~

Das klingt fair für mich. Das Postfix-Inkrement hat eine höhere Priorität als das Präfix-Inkrement, daher wird der Code als r-Wert analysiert int b = ++(i++);und iist ein r-Wert. Daher der Fehler.

Betrachten wir nun diese Variante in Klammern, um die Standardprioritäten zu überschreiben:

int main() {
    int i = 2;
    int b = (++i)++;
    return 3;
}

Dieser Code kompiliert und gibt 3 zurück. Das klingt für mich fair, scheint aber im Widerspruch zum ersten Code zu stehen.

Die Frage: Warum (++i)ist ein lvalueWann inicht?

Vielen Dank!

UPDATE: Die oben gezeigte Fehlermeldung stammt von gcc (x86-64 9.2). Hier ist das genaue Rendering: Fehler mit gcc

Clang x86-64 9.0.0 hat eine ganz andere Meldung: Fehler mit Clang

<source>:3:13: error: expression is not assignable

    int b = ++i++;

            ^ ~~~

Mit GCC haben Sie den Eindruck, dass das Problem beim Postfix-Operator liegt, und Sie können dann herausfinden, warum dies ++iin Ordnung iist, solange dies nicht der Fall ist, daher meine Frage. Bei Clang ist klarer, dass das Problem beim Präfixoperator liegt.

Bktero
quelle
Dies wurde ursprünglich mit C markiert, es ist mit Sicherheit nicht gültig C.
Antti Haapala
Tut mir leid! Ich nahm an, dass das Verhalten in C ...
Bktero

Antworten:

23

iund ++isind beide lWerte, aber es i++ist ein rWert.

++(i++)kann nicht gültig sein, da das Präfix ++angewendet wird i++, was ein r-Wert ist. Ist aber (++i)++in Ordnung, weil ++ies ein Wert ist.

Beachten Sie, dass in C die Situation anders ist. i++und ++isind beide rWerte. (Dies ist ein Beispiel dafür, warum Menschen aufhören sollten anzunehmen, dass C und C ++ dieselben Regeln haben. Menschen nehmen diese Annahmen in ihre Fragen auf, die dann widerlegt werden müssen.)

Brian
quelle
4

Diese Erklärung

int b = ++i++;

ist äquivalent zu

int b = ++( i++ );

Der Postfix-Inkrement-Operator gibt den Wert des Operanden vor dem Inkrement zurück.

Aus dem C ++ 17-Standard (8.2.6 Inkrementieren und Dekrementieren)

1 Der Wert eines Postfix ++ - Ausdrucks ist der Wert seines Operanden ... Das Ergebnis ist ein Wert .

Während der unäre Inkrementoperator nach seinem Inkrement den Wert l zurückgibt. Also diese Erklärung

int b = (++i)++;

ist gültig. Sie könnten zum Beispiel schreiben

int b = (++++++++i)++;

Aus dem C ++ 17 Standard (8.3.2 Inkrementieren und Dekrementieren)

1 Der Operand von Präfix ++ wird durch Hinzufügen von 1 geändert. Der Operand muss ein veränderbarer Wert sein. Der Typ des Operanden muss ein anderer arithmetischer Typ als cv bool oder ein Zeiger auf einen vollständig definierten Objekttyp sein. Das Ergebnis ist der aktualisierte Operand. es ist ein l-Wert und es ist ein Bitfeld, wenn der Operand ein Bitfeld ist ....

Beachten Sie, dass in C beide Operatoren einen Wert anstelle von lvalue zurückgeben. Also in C diese Erklärung

int b = (++i)++;

ist ungültig.

Vlad aus Moskau
quelle
3

Der Code wird also als int b = ++ (i ++) analysiert. und ich bin ein Wert.

Nein iist kein Wert. iist ein Wert. i++ist ein r-Wert (genauer gesagt ein Wert).

Eerorika
quelle