Namensräume
Varianten
Aktionen

Wertkategorien

Von cppreference.com
< c‎ | Sprache

Jeder Ausdruck in C (ein Operator mit seinen Operanden, ein Funktionsaufruf, eine Konstante, ein Variablenname usw.) wird 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.

Inhalt

[bearbeiten] Lvalue-Ausdrücke

Ein lvalue-Ausdruck ist jeder Ausdruck mit einem Objekttyp außer dem Typ void, der potenziell ein Objekt bezeichnet (das Verhalten ist undefiniert, wenn ein lvalue beim Auswerten tatsächlich kein Objekt bezeichnet). Mit anderen Worten, ein lvalue-Ausdruck wertet zur Objektidentität aus. Der Name dieser Wertkategorie ("linke Seite") ist historisch und spiegelt die Verwendung von lvalue-Ausdrücken als linken Operanden des Zuweisungsoperators in der CPL-Programmiersprache 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 genannten Operatoren verwendet wird, durchlaufen Nicht-Array-lvalues eines beliebigen vollständigen Typs eine lvalue-Konvertierung, die das Lesen des Wertes des Objekts von seinem Speicherort modelliert. Ebenso durchlaufen Array-lvalues eine Array-zu-Zeiger-Konvertierung, wenn sie in einem anderen Kontext als sizeof, _Alignof, dem Adressoperator oder der Array-Initialisierung aus einem Zeichenkettenliteral verwendet werden.

Die Semantik von const/volatile/restrict-Qualifizierern und atomaren Typen gilt nur für lvalues (die lvalue-Konvertierung entfernt die Qualifizierer und die Atomizität).

Die folgenden Ausdrücke sind lvalues:

  • Bezeichner, einschließlich benannter Funktionsparameter, sofern sie als Objekte (nicht Funktionen oder Aufzählungskonstanten) deklariert wurden.
  • Zeichenkettenliterale.
  • (C99) Compound Literals.
  • Ausdrücke in Klammern, wenn der nicht in Klammern gesetzte Ausdruck ein lvalue ist.
  • das Ergebnis eines Mitgliedszugriffsoperators (Punkt) , wenn sein linker Operand ein lvalue ist.
  • das Ergebnis des Mitgliedszugriffs über einen Zeiger -> Operator.
  • das Ergebnis des Dereferenzierungsoperators (unärer *), angewendet auf einen Zeiger auf ein Objekt.
  • das Ergebnis des Subskriptionsoperators ([]).

[bearbeiten] Modifizierbare lvalue-Ausdrücke

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

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

[bearbeiten] 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 keinen Speicherort haben. Die Adresse eines Nicht-lvalue-Objektausdrucks kann nicht genommen werden.

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

  • Integer-, Zeichen- und Gleitkommakonstanten.
  • alle Operatoren, die nicht zum Zurückgeben von lvalues spezifiziert sind, einschließlich:
  • jedes Funktionsaufrufausdrucks.
  • jedes Cast-Ausdrucks (beachten Sie, dass Compound Literals, die ähnlich aussehen, lvalues sind).
  • Mitgliedszugriffsoperator (Punkt) angewendet auf eine 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äfixformen sind in C++ lvalues).
  • Ergebnisse von Zuweisungsoperatoren (Hinweis: sind auch in C++ lvalues).
  • 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 dies ist).
  • der Adressoperator, selbst wenn er durch Anwendung auf das Ergebnis des unären * Operators neutralisiert wird.

Als Sonderfall werden Ausdrücke vom Typ void als Nicht-lvalue-Objektausdrücke angenommen, die einen Wert liefern, der keine Repräsentation hat und keinen Speicherplatz benötigt.

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

[bearbeiten] Funktionsbezeichner-Ausdruck

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

[bearbeiten] Referenzen

  • 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.

[bearbeiten] Siehe auch

C++ Dokumentation für Wertkategorien