Namespaces
Variants

Value categories

From cppreference.net

Jeder Ausdruck in C (ein Operator mit seinen Argumenten, ein Funktionsaufruf, eine Konstante, ein Variablenname, etc.) ist durch zwei unabhängige Eigenschaften charakterisiert: einen Typ und eine Wertkategorie .

Jeder Ausdruck gehört zu einer von drei Wertkategorien: Lvalue, Nicht-Lvalue-Objekt (Rvalue) und Funktionsbezeichner.

Inhaltsverzeichnis

Lvalue-Ausdrücke

Lvalue-Ausdruck ist jeder Ausdruck mit Objekttyp außer dem Typ void , der potenziell ein Objekt bezeichnet (das Verhalten ist undefiniert, wenn ein Lvalue bei Auswertung tatsächlich kein Objekt bezeichnet). Mit anderen Worten, ein Lvalue-Ausdruck ergibt die Objektidentität  . Der Name dieser Wertkategorie ("left value") ist historisch und spiegelt die Verwendung von Lvalue-Ausdrücken als linken Operanden des Zuweisungsoperators in der Programmiersprache CPL wider.

Lvalue-Ausdrücke können in den folgenden Lvalue-Kontexten verwendet werden:

Wenn ein Lvalue-Ausdruck in einem anderen Kontext als sizeof , _Alignof oder den oben aufgeführten Operatoren verwendet wird, unterliegen Nicht-Array-Lvalues jedes vollständigen Typs der Lvalue-Konvertierung , die das Laden des Wertes des Objekts aus seinem Speicherort modelliert. Ebenso unterliegen Array-Lvalues der Array-zu-Zeiger-Konvertierung , wenn sie in einem anderen Kontext als sizeof , _Alignof , dem Adressoperator oder der Array-Initialisierung aus einem String-Literal verwendet werden.

Die Semantik der const / volatile / restrict -Qualifizierer und atomaren Typen gilt nur für L-Werte (L-Wert-Konvertierung entfernt die Qualifizierer und hebt die Atomarität auf).

Die folgenden Ausdrücke sind Lvalues:

  • Bezeichner, einschließlich Funktionsparameternamen, sofern sie als Bezeichner für Objekte (nicht für Funktionen oder Aufzählungskonstanten) deklariert wurden
  • String-Literale
  • (C99) Verbundliterale
  • eingeklammerter Ausdruck, wenn der nicht eingeklammerte Ausdruck ein L-Wert ist
  • das Ergebnis eines Elementzugriffs (Punkt-Operators), wenn sein linkes Argument ein L-Wert ist
  • das Ergebnis eines Elementzugriffs durch Zeiger -> Operator
  • das Ergebnis des Dereferenzierungs- (unären * ) Operators, angewendet auf einen Zeiger auf ein Objekt
  • das Ergebnis des Index-Operators ( [] )

Modifizierbare Lvalue-Ausdrücke

Ein modifizierbarer L-Wert ist jeder L-Wert-Ausdruck eines vollständigen, nicht-Array-Typs, der nicht const -qualifiziert ist, und, falls es sich um eine Struktur/Union handelt, keine Mitglieder hat, die const -qualifiziert sind, rekursiv.

Nur modifizierbare Lvalue-Ausdrücke dürfen als Argumente für Inkrement/Dekrement sowie als linke Operanden von Zuweisungs- und zusammengesetzten Zuweisungsoperatoren verwendet werden.

Nicht-Lvalue-Objektausdrücke

Bekannt als rvalues  , sind nicht-lvalue Objektausdrücke Ausdrücke von Objekttypen, die keine Objekte bezeichnen, sondern Werte, die keine Objektidentität oder Speicherstelle besitzen. Die Adresse eines nicht-lvalue Objektausdrucks kann nicht genommen werden.

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

  • Integer-, Zeichen- und Fließkommakonstanten
  • Alle Operatoren, die nicht spezifiziert sind, L-Werte zurückzugeben, einschließlich
  • jeder Funktionsaufrufausdruck
  • jeder Cast-Ausdruck (beachte, dass zusammengesetzte Literale, die ähnlich aussehen, Lvalues sind)
  • Member-Zugriffsoperator (Punkt) angewendet auf einen Nicht-Lvalue-Struktur/Union, f ( ) . x , ( x, s1 ) . a , ( s1 = s2 ) . m
  • Ergebnisse aller arithmetischen, relationalen, logischen und bitweisen Operatoren
  • Ergebnisse von Inkrement- und Dekrementoperatoren (Hinweis: Präfix-Formen sind in C++ Lvalues)
  • Ergebnisse von Zuweisungsoperatoren (Hinweis: ebenfalls Lvalues in C++)
  • der Bedingungsoperator (Hinweis: ist in C++ ein Lvalue, wenn sowohl der zweite als auch der dritte Operand Lvalues desselben Typs sind)
  • der Kommaoperator (Hinweis: ist in C++ ein Lvalue, wenn der zweite Operand ein Lvalue ist)
  • der Adressoperator, selbst wenn neutralisiert durch Anwendung auf das Ergebnis des unären * Operators

Als Sonderfall werden Ausdrücke vom Typ void als nicht-lvalue Objektausdrücke betrachtet, die einen Wert liefern, der keine Darstellung hat und keinen Speicher benötigt.

Beachten Sie, dass ein Struct/Union-Rvalue, der ein Mitglied (möglicherweise verschachtelt) vom Array-Typ hat, tatsächlich ein Objekt mit temporärer Lebensdauer bezeichnet. Dieses Objekt kann durch Lvalue-Ausdrücke zugegriffen werden, die durch Indizierung des Array-Mitglieds oder durch Dereferenzierung des Zeigers gebildet werden, der durch Array-zu-Zeiger-Konvertierung des Array-Mitglieds erhalten wird.

(seit C99)

Funktionsbezeichner-Ausdruck

Ein Funktionsbezeichner (der durch eine Funktionsdeklaration eingeführte Bezeichner) ist ein Ausdruck vom Funktionstyp. Wenn er in einem anderen Kontext als dem Adressoperator, sizeof , und _Alignof verwendet wird (die letzten beiden erzeugen Kompilierfehler, wenn sie auf Funktionen angewendet werden), wird der Funktionsbezeichner immer in einen Nicht-Lvalue-Zeiger auf Funktion konvertiert. Beachten Sie, dass der Funktionsaufrufoperator für Zeiger auf Funktionen definiert ist und nicht für Funktionsbezeichner selbst.

Referenzen

  • C23-Standard (ISO/IEC 9899:2024):
  • 6.3.2.1 Lvalues, Arrays und Funktionsbezeichner (S: 48-49)
  • C17-Standard (ISO/IEC 9899:2018):
  • 6.3.2.1 Lvalues, Arrays und Funktionsbezeichner (S: 40)
  • C11-Standard (ISO/IEC 9899:2011):
  • 6.3.2.1 Lvalues, Arrays und Funktionsbezeichner (S: 54-55)
  • C99-Standard (ISO/IEC 9899:1999):
  • 6.3.2.1 Lvalues, Arrays und Funktionsbezeichner (S: 46)
  • C89/C90 Standard (ISO/IEC 9899:1990):
  • 3.2.2.1 Lvalues und Funktionsbezeichner

Siehe auch

C++-Dokumentation für Wertkategorien