Warum funktionieren mehrere Dekrementoperatoren nicht in C, wenn sie in C++ funktionieren?

Lesezeit: 3 Minuten

Benutzeravatar von MD XF
MDXF

Wenn Sie sich diese Frage ansehen und einen Teil des Codes ausprobieren:

int x = 100;

while ( 0 <-------------------- x )
{
    printf("%d ", x);
}

Ich habe versucht, mit zu kompilieren gcc und bekam folgenden Fehler:

file.c: In function 'main':
file:c:10:27: error: lvalue required as decrement operand
 while ( 0 <-------------------- x )

Aber Kompilieren mit g++ funktioniert. Warum ist dieser Code in C++ gültig, aber nicht in C?

  • Weil C und C++ zwei verschiedene Sprachen sind. Mit anderen Worten, C und C++ sind nicht dieselbe Sprache.

    – Kerrek SB

    20. Februar 2017 um 23:28 Uhr

  • @chqrlie Zirkelschluss. F: Warum kommt Wasser aus meinem Wasserhahn und nicht Pepsi? A: Weil Wasserhähne verwendet werden können, um leicht auf Wasser zuzugreifen.

    – Benutzer253751

    20. Februar 2017 um 23:45 Uhr

  • In C können Sie es umgehen, indem Sie schreiben while (0 < (x -= 10)).

    – dan04

    20. Februar 2017 um 23:58 Uhr

  • Alternativ, um den ausgefallenen Stil des OP beizubehalten, while (0 < (x +=-+-+- 10))

    – chqrlie

    21. Februar 2017 um 0:00 Uhr

  • “Aber das Kompilieren mit g++ funktioniert. Warum ist dieser Code in C++ gültig, aber nicht in C?” – Nur weil g++ (oder jeder andere Compiler) es akzeptiert, bedeutet das nicht automatisch, dass es sich um gültigen C++-Code handelt. Vergiss das niemals.

    – Marcelm

    21. Februar 2017 um 12:29 Uhr

In C, --x ist ein Wert, kein Lvalue. Seine Wirkung besteht darin, zu dekrementieren xund mit dem neu zugewiesenen Wert von auswerten x. Seit --x kein Lvalue ist, kann er nicht dekrementiert werden.

In C++, --x ist ein lvalue, kein rvalue. Seine Wirkung besteht darin, zu dekrementieren xund auswerten x als lvalue. Seit --x wieder ein Lvalue ist, kann er wieder dekrementiert werden.

Der Grund, warum es sinnvoll ist --x In C++ ein lvalue zu sein, liegt daran, dass C++ Referenztypen eingeführt hat. Gegeben

void f(int &);
int i;

Anrufen kann sinnvoll sein f(--i)die geht i durch Referenz nach dem Dekrementieren.

Da C keine Referenztypen hat, macht es wenig Sinn --i ein lvalue sein. Historisch gesehen war dies nie der Fall, und im Gegensatz zu C++ erhielt C nie einen zwingenden Grund, die Regeln zu ändern.

Beachten Sie, dass C++ umfangreichere Änderungen erforderte als das Vornehmen --x ein lvalue, um es tatsächlich funktionieren zu lassen. Herstellung --x ein lvalue, ohne irgendetwas anderes, würde machen --x undefiniertes Verhalten, weil es keinen Sequenzpunkt zwischen der Änderung zu geben würde x und die anschließende lvalue-to-value-Konvertierung. Noch deutlicher also für ----x. C++ musste die Sequenzierungsregeln ändern, damit es funktionierte. In C können Änderungen an den Sequenzregeln Probleme für vorhandene Compiler verursachen, um sich an die neuen Regeln anzupassen, sodass solche Änderungen wahrscheinlich abgelehnt werden, es sei denn, es gibt einen großen Vorteil.

  • Du könntest immer noch so etwas sagen wie f(&--x). Ich bin mir nicht sicher, ob ich Ihren Grund kaufe, warum “es keinen Sinn macht” in C.

    – Kerrek SB

    20. Februar 2017 um 23:23 Uhr

  • @KerrekSB Fairer Punkt, aber es gibt immer noch wenig Sinn. ich würde sagen f(&--x) ist eher weniger das, was jemand eigentlich schreiben will, als f(--x). Unabhängig davon hat C auch ein Problem, dass Änderungen an den Regeln für bestehende Implementierungen problematisch wären, dazu habe ich etwas hinzugefügt.

    Benutzer743382

    20. Februar 2017 um 23:34 Uhr

  • Das Verhalten von ----x in C++11 geändert (danach wohldefiniert, vorher undefiniert)

    – MM

    21. Februar 2017 um 1:40 Uhr

  • Wenn Sie wirklich wollen f(&--x) in C können Sie tun f((--x,&x)).

    – G-Man sagt „Monica wieder einsetzen“

    21. Februar 2017 um 3:06 Uhr

  • Ich bin mir über den historischen Hintergrund hier nicht sicher, aber meiner Meinung nach ist der überzeugendste Fall, dass die Zuweisung einen lvalue zurückgibt, dass Sie für benutzerdefinierte Klassen wirklich keine Kopie zurückgeben möchten. Dann ist alles andere nur noch Konsistenz.

    – TC

    21. Februar 2017 um 13:36 Uhr

1408480cookie-checkWarum funktionieren mehrere Dekrementoperatoren nicht in C, wenn sie in C++ funktionieren?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy