Konstante Ausdrücke
Mehrere Arten von Ausdrücken werden als konstante Ausdrücke bezeichnet
Inhalt |
[bearbeiten] Präprozessor-konstanter Ausdruck
Der Ausdruck nach #if oder #elif muss expandieren zu
- Operatoren außer Zuweisung, Inkrement, Dekrement, Funktionsaufruf oder Komma, dessen Argumente Präprozessor-konstante Ausdrücke sind
- Ganzzahlige Konstanten
- Zeichenkonstanten
- dem speziellen Präprozessor-Operator
defined
Zeichenkonstanten können bei der Auswertung in #if-Ausdrücken im Quellcode-Zeichensatz, im Ausführungs-Zeichensatz oder einem anderen implementierungsdefinierten Zeichensatz interpretiert werden.
|
Die Ganzzahl-Arithmetik in |
(seit C99) |
[bearbeiten] Ganzzahliger konstanter Ausdruck
Ein ganzzahliger konstanter Ausdruck ist ein Ausdruck, der nur aus
- Operatoren außer Zuweisung, Inkrement, Dekrement, Funktionsaufruf oder Komma besteht, mit der Ausnahme, dass Cast-Operatoren nur arithmetische Typen in Ganzzahl-Typen umwandeln dürfen, es sei denn, sie sind Teil eines Operanden eines sizeof , _Alignof(seit C11)(bis C23), alignas(seit C23) oder typeof/typeof_unqual(seit C23)-Operators.
- Ganzzahlige Konstanten
- Aufzählungskonstanten
- Zeichenkonstanten
- Gleitkommakonstanten, aber nur, wenn sie unmittelbar als Operanden von Casts zu Ganzzahl-Typen verwendet werden
-
sizeof-Operatoren deren Operanden keine VLA sind(seit C99)
|
(seit C11) |
|
(seit C23) |
Ganzzahlige konstante Ausdrücke werden zur Kompilierzeit ausgewertet. Die folgenden Kontexte erfordern Ausdrücke, die als ganzzahlige konstante Ausdrücke bekannt sind
- Die Größe eines Bitfeldes.
- Der Wert einer Aufzählungskonstante
- Das
case-Label einer switch-Anweisung - Die Größe eines nicht-VLA(seit C99)-Arrays
- Implizite Konvertierung von Ganzzahl zu Zeiger.
|
(seit C99) |
|
(seit C11) |
|
(seit C23) |
[bearbeiten] Statischer Initialisierer
Ausdrücke, die in den Initialisierern von Objekten mit statischer und thread_local Speicherdauer oder mit dem constexpr-Speicherklassenspezifizierer deklariert sind(seit C23) verwendet werden, müssen entweder Zeichenkettenliterale oder Ausdrücke sein, die eine der folgenden Formen annehmen können
- Operatoren außer Zuweisung, Inkrement, Dekrement, Funktionsaufruf oder Komma besteht, mit der Ausnahme, dass Cast-Operatoren arithmetische Typen in andere arithmetische Typen umwandeln müssen, es sei denn, sie sind Teil eines Operanden eines sizeof , _Alignof(seit C11)(bis C23), alignof(seit C23) oder typeof/typeof_unqual(seit C23)-Operators
- Ganzzahlige Konstanten
- Gleitkommakonstanten
- Aufzählungskonstanten
- Zeichenkonstanten
-
sizeof-Operatoren deren Operanden keine VLA sind(seit C99)
| (seit C11) |
|
(seit C23) |
- ein Nullzeiger
- lvalue, das ein Objekt mit statischer Speicherdauer oder einen Funktionsdeskriptor bezeichnet, konvertiert entweder
- durch Verwendung des unären Adressoperator
- durch Umwandlung einer Ganzzahlkonstante in einen Zeiger
- durch Array-zu-Zeiger- oder Funktions-zu-Zeiger-implizite Konvertierung
|
5) eine benannte Konstante, die ein Bezeichner ist, der
. auf eine benannte Konstante vom Struktur- oder Union-Typ anwendet, auch rekursiv.6) eine zusammengesetzte literale Konstante, die
Eine Struktur- oder Union-Konstante ist eine benannte Konstante oder eine zusammengesetzte literale Konstante vom Struktur- bzw. Union-Typ. Wenn der Member-Zugriffsoperator |
(seit C23) |
Im Gegensatz zu ganzzahligen konstanten Ausdrücken müssen statische Initialisierer-Ausdrücke nicht zur Kompilierzeit ausgewertet werden; der Compiler ist befugt, solche Initialisierer in ausführbaren Code umzuwandeln, der vor Programmstart aufgerufen wird.
static int i = 2 || 1 / 0; // initializes i to value 1
| Dieser Abschnitt ist unvollständig Grund: andere Mini-Beispiele |
Der Wert eines Gleitkomma-statischen Initialisierers ist niemals weniger genau als der Wert desselben Ausdrucks, der zur Laufzeit ausgeführt wird, aber er kann besser sein.
[bearbeiten] Gleitkommakonstante Ausdrücke
Arithmetische konstante Ausdrücke von Gleitkomma-Typen, die nicht in statischen Initialisierern verwendet werden, werden immer so ausgewertet, als ob sie zur Laufzeit ausgeführt würden, und sind von der aktuellen Rundung betroffen (wenn FENV_ACCESS gesetzt ist) und melden Fehler gemäß den Spezifikationen in math_errhandling.
void f(void) { #pragma STDC FENV_ACCESS ON static float x = 0.0 / 0.0; // static initializer: does not raise an exception float w[] = { 0.0 / 0.0 }; // raises an exception float y = 0.0 / 0.0; // raises an exception double z = 0.0 / 0.0; // raises an exception }
[bearbeiten] Hinweise
Wenn ein Ausdruck einen Wert ergibt, der in seinem Typ nicht darstellbar ist, kann er nicht als konstanter Ausdruck verwendet werden.
Implementierungen können andere Formen von konstanten Ausdrücken akzeptieren. Diese konstanten Ausdrücke werden jedoch nicht als ganzzahlige konstante Ausdrücke, arithmetische konstante Ausdrücke oder Adresskonstante Ausdrücke betrachtet und können daher nicht in Kontexten verwendet werden, die diese Arten von konstanten Ausdrücken erfordern. Zum Beispiel deklariert int arr[(int)+1.0]; einen VLA.
[bearbeiten] Referenzen
- C23-Standard (ISO/IEC 9899:2024)
- 6.6 Konstante Ausdrücke (p: TBD)
- C17-Standard (ISO/IEC 9899:2018)
- 6.6 Konstante Ausdrücke (p: 76-77)
- C11-Standard (ISO/IEC 9899:2011)
- 6.6 Konstante Ausdrücke (p: 106-107)
- C99-Standard (ISO/IEC 9899:1999)
- 6.6 Konstante Ausdrücke (p: 95-96)
- C89/C90-Standard (ISO/IEC 9899:1990)
- 3.4 KONSTANTE AUSDRÜCKE
[bearbeiten] Siehe auch
| C++ Dokumentation für Konstante Ausdrücke
|