Namensräume
Varianten
Aktionen

Konstante Ausdrücke

Von cppreference.com
< c‎ | Sprache

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

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

(seit C99)

[bearbeiten] Ganzzahliger konstanter Ausdruck

Ein ganzzahliger konstanter Ausdruck ist ein Ausdruck, der nur aus

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

Ganzzahlige konstante Ausdrücke werden zur Kompilierzeit ausgewertet. Die folgenden Kontexte erfordern Ausdrücke, die als ganzzahlige konstante Ausdrücke bekannt sind

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

1) arithmetischer konstanter Ausdruck, der ein Ausdruck eines beliebigen arithmetischen Typs ist, der aus
(seit C11)
  • benannte oder zusammengesetzte literale Konstanten arithmetischen Typs
(seit C23)
2) eine Nullzeiger-Konstante (z.B. NULL)
3) Adresskonstanter Ausdruck, der
  • 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
4) ein Adresskonstanter Ausdruck eines beliebigen vollständigen Objekt-Typs, plus oder minus einem ganzzahligen konstanten Ausdruck
5) eine benannte Konstante, die ein Bezeichner ist, der
  • eine Aufzählungskonstante
  • eine vordefinierte Konstante (eine 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 literale Konstante, die
  • ein zusammengesetztes Literal mit dem Speicherklassenspezifizierer constexpr ist
  • ein Postfix-Ausdruck, der den Member-Zugriffsoperator . auf eine zusammengesetzte literale Konstante vom Struktur- oder Union-Typ anwendet, auch rekursiv.

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

(seit C23)
7) ein konstanter Ausdruck einer anderen Form, die von der Implementierung akzeptiert wird.

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

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