Namespaces
Variants

Constant expressions

From cppreference.net

Mehrere Arten von Ausdrücken werden als constant expressions bezeichnet.

Inhaltsverzeichnis

Präprozessor-Konstantenausdruck

Der Ausdruck nach #if oder #elif muss expandieren zu

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 #if -Ausdrücken wird mit der Semantik von intmax_t für vorzeichenbehaftete Typen und uintmax_t für vorzeichenlose Typen durchgeführt.

(seit C99)

Ganzzahliger konstanter Ausdruck

Ein konstanter Integer-Ausdruck ist ein Ausdruck, der nur aus

  • _Alignof (bis C23) alignas (seit C23) Operatoren
(seit C11)
  • benannte und zusammengesetzte Literalkonstanten, die vom Ganzzahltyp sind oder die vom arithmetischen Typ sind und die unmittelbaren Operanden von Casts sind
(seit C23)

Integer constant expressions werden zur Kompilierzeit ausgewertet. Die folgenden Kontexte erfordern Ausdrücke, die als Integer Constant Expressions bezeichnet werden:

(seit C99)
(seit C11)
  • Die Anzahl der Bits N eines bitgenauen Ganzzahltyps ( _BitInt ( N ) )
(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

1) arithmetischer konstanter Ausdruck , welcher ein Ausdruck eines beliebigen arithmetischen Typs ist, der aus
(seit C11)
  • benannte oder zusammengesetzte Literalkonstanten arithmetischen Typs
(seit C23)
2) eine Nullzeiger-Konstante (z.B., NULL ).
3) address constant expression , die ist
  • 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 .
4) address constant expression eines vollständigen Objekttyps, plus oder minus einem integer constant expression .
5) eine benannte Konstante , die ein Bezeichner ist, der
  • ein Aufzählungskonstante ist
  • eine vordefinierte Konstante (einer von true , false oder nullptr )
  • mit dem Speicherklassenspezifizierer constexpr deklariert ist und einen Objekttyp hat
oder ein Postfix-Ausdruck, der den . Member-Zugriffsoperator auf eine benannte Konstante vom Struktur- oder Union-Typ anwendet, auch rekursiv.
6) eine zusammengesetzte Literalkonstante , die
  • ein zusammengesetztes Literal mit Speicherklassenspezifizierer constexpr ist
  • ein Postfix-Ausdruck, der den . Member-Zugriffsoperator auf eine zusammengesetzte Literalkonstante vom Struktur- oder Union-Typ anwendet, auch rekursiv.

Eine Struktur- oder Union-Konstante ist eine benannte Konstante oder zusammengesetzte Literalkonstante mit Struktur- bzw. Union-Typ. Wenn der Member-Zugriffsoperator . auf ein Mitglied einer Union-Konstante zugreift, muss das zugriffene Mitglied dasselbe sein wie das Mitglied, das durch den Initialisierer der Union-Konstante initialisiert wird.

(seit C23)
7) konstanter Ausdruck einer der anderen vom Implementierung akzeptierten Formen.

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

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