Value categories
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:
- als Operand des Adressoperators (außer wenn der L-Wert ein Bitfeld bezeichnet oder als register deklariert wurde).
- als Operand der Prä-/Post- Inkrement- und Dekrementoperatoren .
- als linker Operand des Elementzugriffsoperators (Punkt-Operator).
- als linker Operand der Zuweisungs- und zusammengesetzten Zuweisungsoperatoren .
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
|