Constant expressions
Mehrere Arten von Ausdrücken werden als constant expressions bezeichnet.
Inhaltsverzeichnis |
Präprozessor-Konstantenausdruck
Der Ausdruck nach
#if
oder
#elif
muss expandieren zu
- Operatoren außer Zuweisung , Inkrement, Dekrement , Funktionsaufruf , oder Komma , deren Argumente Präprozessor-Konstantenausdrücke sind
- Ganzzahlkonstanten
- Zeichenkonstanten
-
der spezielle Präprozessor-Operator
defined.
Zeichenkonstanten, wenn ausgewertet in
#if
-Ausdrücken, können interpretiert werden im Quell-Zeichensatz, dem Ausführungs-Zeichensatz oder einem anderen implementierungsdefinierten Zeichensatz.
|
Integer-Arithmetik in
|
(seit C99) |
Ganzzahliger konstanter Ausdruck
Ein konstanter Integer-Ausdruck ist ein Ausdruck, der nur aus
- Operatoren außer Zuweisung , Inkrement, Dekrement , Funktionsaufruf , oder Komma , mit der Ausnahme, dass Cast -Operatoren nur arithmetische Typen in Ganzzahltypen umwandeln können, es sei denn, sie sind Teil eines Operanden für einen sizeof , _Alignof (seit C11) (bis C23) , alignas (seit C23) oder typeof/typeof_unqual (seit C23) -Operator.
- Ganzzahlige Konstanten
- Aufzählungskonstanten
- Zeichenkonstanten
- Gleitkommakonstanten , aber nur wenn sie unmittelbar als Operanden von Casts in Ganzzahltypen verwendet werden
-
sizeof-Operatoren deren Operanden keine VLA sind (seit C99)
|
(seit C11) |
|
(seit C23) |
Integer constant expressions werden zur Kompilierzeit ausgewertet. Die folgenden Kontexte erfordern Ausdrücke, die als Integer Constant Expressions bezeichnet werden:
- Die Größe eines Bit-Felds .
- Der Wert einer Aufzählungskonstante
-
Die
case-Marke einer switch-Anweisung - Die Größe eines Nicht-VLA (seit C99) Arrays
- Ganzzahl-zu-Zeiger implizite Konvertierung .
|
(seit C99) |
|
(seit C11) |
|
(seit C23) |
Statischer Initialisierer
Ausdrücke, die in den Initialisierern von Objekten mit static und thread_local Speicherdauer oder deklariert mit dem constexpr Speicherklassen-Spezifizierer (since C23) verwendet werden, müssen entweder Zeichenkettenliterale oder Ausdrücke sein, die einer der folgenden sein können
-
- Operatoren außer Zuweisung , Inkrement, Dekrement , Funktionsaufruf oder Komma besteht, außer dass Cast -Operatoren arithmetische Typen in andere arithmetische Typen umwandeln müssen, es sei denn, sie sind Teil eines Operanden für einen sizeof , _Alignof (seit C11) (bis C23) , alignof (seit C23) oder typeof/typeof_unqual (seit C23) -Operator
- Integer-Konstanten
- Fließkomma-Konstanten
- Aufzählungskonstanten
- Zeichenkonstanten
-
sizeof-Operatoren deren Operanden keine VLA sind (seit C99)
| (seit C11) |
|
(seit C23) |
-
- ein Nullzeiger
- lvalue , der auf ein Objekt mit statischer storage duration oder einen Funktionsbezeichner verweist, konvertiert zu einem Zeiger entweder
-
- durch Verwendung des unären Adressoperators
- durch Konvertierung einer Integer-Konstante zu einem Zeiger
- durch Array-zu-Zeiger oder Funktion-zu-Zeiger implizite conversion .
|
5)
eine
benannte Konstante
, die ein Bezeichner ist, der
.
Member-Zugriffsoperator auf eine benannte Konstante vom Struktur- oder Union-Typ anwendet, auch rekursiv.
6)
eine
zusammengesetzte Literalkonstante
, die
Eine
Struktur- oder Union-Konstante
ist eine benannte Konstante oder zusammengesetzte Literalkonstante mit Struktur- bzw. Union-Typ. Wenn der Member-Zugriffsoperator
|
(seit C23) |
Im Gegensatz zu ganzzahligen konstanten Ausdrücken müssen statische Initialisierungsausdrücke nicht zur Kompilierzeit ausgewertet werden; dem Compiler steht es frei, solche Initialisierer in ausführbaren Code umzuwandeln, der vor dem Programmstart aufgerufen wird.
static int i = 2 || 1 / 0; // initialisiert i mit dem Wert 1
|
Dieser Abschnitt ist unvollständig
Grund: weitere Mini-Beispiele |
Der Wert eines statischen Gleitkomma-Initialisierers ist niemals ungenauer als der Wert desselben Ausdrucks zur Laufzeit, kann jedoch besser sein.
Gleitkomma-Konstantenausdrücke
Arithmetische Konstantenausdrücke von Gleitkommatypen, die nicht in statischen Initialisierern verwendet werden, werden stets so ausgewertet, als ob sie zur Laufzeit ausgeführt würden, und werden beeinflusst durch die aktuelle Rundung (falls FENV_ACCESS aktiviert ist) und melden Fehler gemäß math_errhandling .
void f(void) { #pragma STDC FENV_ACCESS ON static float x = 0.0 / 0.0; // statischer Initialisierer: löst keine Exception aus float w[] = { 0.0 / 0.0 }; // löst eine Exception aus float y = 0.0 / 0.0; // löst eine Exception aus double z = 0.0 / 0.0; // löst eine Exception aus }
Hinweise
Wenn ein Ausdruck einen Wert ergibt, der nicht durch seinen Typ darstellbar ist, kann er nicht als konstanter Ausdruck verwendet werden.
Implementierungen können andere Formen konstanter Ausdrücke akzeptieren. Diese konstanten Ausdrücke werden jedoch nicht als Integer-Konstantenausdrücke, arithmetische Konstantenausdrücke oder Adress-Konstantenausdrücke betrachtet und können daher nicht in Kontexten verwendet werden, die diese Arten konstanter Ausdrücke erfordern. Zum Beispiel, int arr [ ( int ) + 1.0 ] ; deklariert ein VLA.
Referenzen
- C23-Standard (ISO/IEC 9899:2024):
-
- 6.6 Konstantenausdrücke (S: 95-96)
- C17-Standard (ISO/IEC 9899:2018):
-
- 6.6 Konstante Ausdrücke (S: 76-77)
- C11-Standard (ISO/IEC 9899:2011):
-
- 6.6 Konstantenausdrücke (S: 106-107)
- C99-Standard (ISO/IEC 9899:1999):
-
- 6.6 Konstantenausdrücke (S: 95-96)
- C89/C90 Standard (ISO/IEC 9899:1990):
-
- 3.4 KONSTANTE AUSDRÜCKE
Siehe auch
|
C++ Dokumentation
für
Constant expressions
|