Warum sind mehrere Vorinkremente in C++ erlaubt, aber nicht in C? [duplicate]

Lesezeit: 6 Minuten

Benutzeravatar von code_dragon
code_drache

Warum ist

int main()
{
    int i = 0;
    ++++i;
}

gültiges C++, aber kein gültiges C?

  • Warum sollten sich verschiedene Sprachen identisch verhalten?

    – Gerhardh

    11. Januar 2018 um 9:17 Uhr

  • Das ist eine gute Frage, die zufällig schlecht formuliert ist. Warum hat sich Stroustrup dafür entschieden, den Präinkrement-Operator in C++ einen L-Wert liefern zu lassen, wenn er in C keinen L-Wert lieferte? Ich erinnere mich, dass ich die Antwort irgendwo auf dieser Seite gesehen habe, aber ich kann mich nicht erinnern, was es war.

    – Brian Bi

    11. Januar 2018 um 9:33 Uhr


  • Ich weiß auch, dass C und C++ verschiedene Sprachen sind, aber der aktuelle C++-Standard sagt immer noch in [intro.scope] C++ ist eine Allzweck-Programmiersprache, die auf der Programmiersprache C basiert. Außerdem die C++-Standardbibliothek ausdrücklich enthält die C-Standardbibliothek (20.2 Die C-Standardbibliothek [library.c]). Und selbst wenn die Frage nicht so gut ist, beinhaltet die Antwort darauf zu verstehen, was ein lvalue ist. Es ist wirklich schade, dass jede Frage nach feinen Unterschieden einen solchen Flammenkrieg erhält.

    – Serge Ballesta

    11. Januar 2018 um 9:39 Uhr

  • Und in der Tat sehe ich nichts Falsches an dieser Frage. Compilermeldungen vom C-Compiler wären hilfreich gewesen, aber das war es auch schon. Der Code selbst macht in einem echten Programm vielleicht keinen Sinn, aber dafür ist das language-lawyer-Tag da.

    – Ludin

    11. Januar 2018 um 9:56 Uhr

  • Ich habe eine Diskussion auf Meta über die starke Ablehnung dieser Frage eröffnet

    – Serge Ballesta

    11. Januar 2018 um 10:34 Uhr

StoryTeller - Benutzeravatar von Unslander Monica
StoryTeller – Unslander Monica

C und C++ sagen unterschiedliche Dinge über das Ergebnis des Präfixes ++ aus. In C++:

[expr.pre.incr]

Der Operand des Präfixes ++ wird durch Hinzufügen von 1 modifiziert. Der Operand soll ein modifizierbarer L-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 lvalue, und es ist ein Bitfeld, wenn der Operand ein Bitfeld ist. Der Ausdruck ++x entspricht x+=1.

Also kann ++ wieder auf das Ergebnis angewendet werden, da das Ergebnis im Grunde nur das Objekt ist, das inkrementiert wird, und ein Lvalue ist. In C jedoch:

6.5.3 Unäre Operatoren

Der Operand des Präfix-Inkrement- oder -Dekrement-Operators muss einen atomaren, qualifizierten oder nicht qualifizierten Real- oder Zeigertyp haben, und soll ein modifizierbarer lvalue sein.

Der Wert des Operanden des Präfix-Operators ++ wird inkrementiert. Das Ergebnis ist der neue Wert des Operanden nach der Inkrementierung.

Das Ergebnis ist kein Lvalue; es ist nur der reine Wert der Inkrementierung. Sie können also keinen Operator anwenden, der einen Lvalue erfordert, einschließlich ++.

Wenn Ihnen jemals gesagt wird, dass C++ und C eine Obermenge oder Untermenge voneinander sind, wissen Sie, dass dies nicht der Fall ist. Es gibt viele Unterschiede, die diese Behauptung falsch machen.

  • Ich bin kein Downvoter (und ich bin auch kein C- oder C++-Entwickler), aber ein möglicher Grund für ein Downvoter ist, dass dies nur bei “Warum?” aus einem blickwinkel – wie unterscheiden sich die spezifikationen und wie wirkt sich das aus? – und vermisst, was ist möglicherweise ein interessanteres und aufschlussreicheres: was motiviert diese Spezifikationsunterschiede? Gibt es Unterschiede in den Designprinzipien zwischen C und C++, aus denen sich dieser Spezifikationsunterschied natürlich ergibt? Oder Funktionen in C++, die rendern ++++x eine nützliche Sache zu erlauben, wenn es nicht in C wäre? Diese Vorstellung von “warum?” wird in beiden Antworten noch nicht angesprochen.

    – Mark Amery

    11. Januar 2018 um 10:53 Uhr


  • @MarkAmery – Ich hätte es gerne zur Verfügung gestellt. Aber diese Information konnte ich bis jetzt noch nicht wiederherstellen. Es ist eine historische Divergenz, von der ich glaube, dass sie nicht oft diskutiert wurde.

    – StoryTeller – Unslander Monica

    11. Januar 2018 um 10:56 Uhr


Benutzeravatar von Bathsheba
Bathseba

In C war das schon immer so. Möglicherweise weil vorinkrementiert ++ kann auf vielen CPUs auf einen einzigen Maschinencodebefehl optimiert werden, einschließlich solcher aus den 1970er Jahren, als die ++ Konzept entwickelt.

In C++ muss jedoch die Symmetrie beim Überladen von Operatoren berücksichtigt werden. Passend zu C, dem kanonischen Vorinkrement ++ zurück müssten const &, es sei denn, Sie hatten ein unterschiedliches Verhalten für benutzerdefinierte und integrierte Typen (was ein Geruch wäre). Einschränkung der Rückgabe auf const & ist eine Erfindung. Also die Rückgabe von ++ wird von den C-Regeln gelockert, auf Kosten einer erhöhten Compiler-Komplexität, um CPU-Optimierungen für eingebaute Typen auszunutzen.

  • +1. Aber ich denke, das Argument der Operatorüberladung ist ein bisschen zirkulär. Wir haben Canon, weil “Wir sollten es tun wie die kleinen Ints”. Aber warum machen die Ints das dann?

    – StoryTeller – Unslander Monica

    11. Januar 2018 um 11:03 Uhr


  • @StoryTeller: Ich denke, das ist ein Fall, in dem int gesehen class kommen: wenn wir uns bewerben werden ++ zu Objekten des Klassentyps, ohne sie zu kopieren, könnten wir es genauso gut auch für primitive Typen tun. ?: ist genauso.

    – Davis Hering

    11. Januar 2018 um 14:34 Uhr

  • @DavisHerring – Vielleicht. Es ist auch möglich, andere Redewendungen zu erleichtern. Aber ich habe keine Ahnung welche. Ich stimme immer noch Bathsebas Einschätzung zu, verstehen Sie mich nicht falsch.

    – StoryTeller – Unslander Monica

    11. Januar 2018 um 14:37 Uhr


  • @DavisHerring: Überlastung ?: ist im aktuellen Sprachrahmen so gut wie unmöglich, da nur zwei der drei Ausdrücke, aus denen der Operator besteht, jemals ausgewertet werden.

    – Bathseba

    11. Januar 2018 um 14:39 Uhr

  • @Bathsheba: Natürlich; ich meinte (flag ? obj : other).setFoo(1);die nur funktionieren kann, wenn ?: kann einen lvalue zurückgeben, wieder anders als C. Entschuldigung, ich war unklar.

    – Davis Hering

    11. Januar 2018 um 14:43 Uhr

Benutzeravatar von iBug
iBug

Ich nehme an, Sie verstehen, warum es in C++ in Ordnung ist, also werde ich nicht näher darauf eingehen.

Für was auch immer es wert ist, hier ist mein Testergebnis:

t.c:6:2: error: lvalue required as increment operand
  ++ ++c;
  ^

Bezüglich CppReferenz:

Nicht-lvalue-Objektausdrücke

Umgangssprachlich als Rvalues ​​bezeichnet, sind Nicht-Lvalue-Objektausdrücke die Ausdrücke von Objekttypen, die keine Objekte bezeichnen, sondern Werte, die keine Objektidentität oder Speicherort haben. Die Adresse eines Nicht-lvalue-Objektausdrucks kann nicht genommen werden.

Die folgenden Ausdrücke sind Nicht-lvalue-Objektausdrücke:

  • alle Operatoren nicht angegeben, um lvalues ​​zurückzugebeneinschließlich

    • Inkrement- und Dekrementoperatoren (Hinweis: Vorformen sind Lvalues ​​in C++)

Und Abschnitt 6.5.3.1 von n1570:

Der Wert des Operanden des Präfix-Operators ++ wird inkrementiert. Das Ergebnis ist das Neue Wert des Operanden nach der Inkrementierung.

In C sind das Ergebnis der Präfix-Inkrement- und Präfix-Dekrement-Operatoren muss kein lvalue sein, also nicht wieder inkrementierbar. Tatsächlich kann ein solches Wort als “erforderlicher Rvalue” verstanden werden.

Caleths Benutzeravatar
Caleth

Die anderen Antworten erklären, wie die Standards in ihren Anforderungen voneinander abweichen. Diese Antwort liefert ein motivierendes Beispiel im Bereich Differenz.

In C++ können Sie eine Funktion wie haben int& foo(int&);das kein Analogon in C hat. Es ist nützlich (und nicht lästig), dass C++ die Option hat foo(foo(x));.

Stellen Sie sich für einen Moment vor, dass Operationen auf Basistypen irgendwo definiert wurden, z int& operator++(int&);. ++++x selbst ist kein motivierendes Beispiel, aber es passt ins Muster foo Oben.

1400640cookie-checkWarum sind mehrere Vorinkremente in C++ erlaubt, aber nicht in C? [duplicate]

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

Privacy policy