Conditional inclusion
Der Präprozessor unterstützt die bedingte Kompilierung von Teilen einer Quelldatei. Dieses Verhalten wird gesteuert durch die Direktiven
#if
,
#else
,
#elif
,
#ifdef
,
#ifndef
,
#elifdef
,
#elifndef
(seit C23)
und
#endif
.
Inhaltsverzeichnis |
Syntax
#if
Ausdruck
|
|||||||||
#ifdef
Bezeichner
|
|||||||||
#ifndef
Bezeichner
|
|||||||||
#elif
Ausdruck
|
|||||||||
#elifdef
Bezeichner
|
(seit C23) | ||||||||
#elifndef
Bezeichner
|
(seit C23) | ||||||||
#else
|
|||||||||
#endif
|
|||||||||
Erklärung
Der bedingte Präprozessorblock beginnt mit der
#if
-,
#ifdef
- oder
#ifndef
-Direktive, enthält optional beliebig viele
#elif
-,
#elifdef
- oder
#elifndef
(seit C23)
-Direktiven, enthält optional höchstens eine
#else
-Direktive und wird mit der
#endif
-Direktive abgeschlossen. Alle inneren bedingten Präprozessorblöcke werden separat verarbeitet.
Jede der
#if
-,
#ifdef
-,
#ifndef
-,
#elif
-,
#elifdef
-,
#elifndef
(seit C23)
- und
#else
-Direktiven steuert einen Codeblock bis zur ersten
#elif
-,
#elifdef
-,
#elifndef
(seit C23)
-,
#else
- oder
#endif
-Direktive, die nicht zu inneren bedingten Präprozessorblöcken gehört.
#if
,
#ifdef
und
#ifndef
-Direktiven testen die angegebene Bedingung (siehe unten) und wenn diese als wahr ausgewertet wird, kompilieren sie den kontrollierten Codeblock. In diesem Fall werden nachfolgende
#else
,
#elifdef
,
#elifndef
,
(seit C23)
und
#elif
-Direktiven ignoriert. Andernfalls, wenn die angegebene Bedingung als falsch ausgewertet wird, wird der kontrollierte Codeblock übersprungen und die nachfolgende
#else
,
#elifdef
,
#elifndef
,
(seit C23)
oder
#elif
-Direktive (falls vorhanden) wird verarbeitet. Wenn die nachfolgende Direktive
#else
ist, wird der durch die
#else
-Direktive kontrollierte Codeblock bedingungslos kompiliert. Andernfalls verhält sich die
#elif
,
#elifdef
, oder
#elifndef
(seit C23)
-Direktive wie eine
#if
-Direktive: Sie prüft die Bedingung, kompiliert oder überspringt den kontrollierten Codeblock basierend auf dem Ergebnis und verarbeitet im letzteren Fall nachfolgende
#elif
,
#elifdef
,
#elifndef
,
(seit C23)
und
#else
-Direktiven. Der bedingte Präprozessorblock wird durch die
#endif
-Direktive beendet.
Bedingte Auswertung
#if, #elif
Der Ausdruck ist ein konstanter Ausdruck, der nur Konstanten und Bezeichner verwendet, die mit der #define Direktive definiert wurden. Jeder Bezeichner, der kein Literal ist und nicht mit der #define Direktive definiert wurde, ergibt 0 außer true , was zu 1 ergibt (seit C23) .
Der Ausdruck kann unäre Operatoren in der Form
defined
identifier
oder
defined (
identifier
)
enthalten, die
1
zurückgeben, falls der
identifier
mit der
#define
Direktive definiert wurde, andernfalls
0
.
In diesem Kontext werden
__has_include
,
__has_embed
und
__has_c_attribute
so behandelt, als wären sie Namen definierter Makros.
(seit C23)
Wenn der
expression
einen Wert ungleich Null ergibt, wird der kontrollierte Codeblock eingeschlossen, andernfalls übersprungen. Falls eine verwendete Kennung keine Konstante ist, wird sie durch
0
ersetzt.
|
Im Kontext einer Präprozessor-Direktive erkennt ein
|
(seit C23) |
Hinweis: Bis
DR 412
unterscheidet sich
#if
cond1
...
#elif
cond2
von
#if
cond1
...
#else
gefolgt von
#if
cond3
, weil falls
cond1
wahr ist, das zweite
#if
übersprungen wird und
cond3
nicht wohlgeformt sein muss, während
#elif
's
cond2
ein gültiger Ausdruck sein muss. Ab
DR 412
wird auch
#elif
übersprungen, das zum übersprungenen Codeblock führt.
Kombinierte Direktiven
Prüft, ob der Bezeichner als Makroname definiert wurde.
#ifdef
identifier
ist im Wesentlichen gleichbedeutend mit
#if defined
identifier
.
#ifndef
identifier
ist im Wesentlichen äquivalent zu
#if !defined
identifier
.
|
|
(seit C23) |
Hinweise
Während die Direktiven
#elifdef
und
#elifndef
auf C23 abzielen, können Implementierungen sie als konforme Erweiterungen auf ältere Sprachmodi zurückportieren.
Beispiel
#define ABCD 2 #include <stdio.h> int main(void) { #ifdef ABCD printf("1: yes\n"); #else printf("1: no\n"); #endif #ifndef ABCD printf("2: no1\n"); #elif ABCD == 2 printf("2: yes\n"); #else printf("2: no2\n"); #endif #if !defined(DCBA) && (ABCD < 2 * 4 - 3) printf("3: yes\n"); #endif // C23 directives #elifdef/#elifndef #ifdef CPU printf("4: no1\n"); #elifdef GPU printf("4: no2\n"); #elifndef RAM printf("4: yes\n"); // selected in C23 mode, may be selected in pre-C23 mode #else printf("4: no3\n"); // may be selected in pre-C23 mode #endif }
Mögliche Ausgabe:
1: yes 2: yes 3: yes 4: yes
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrektes Verhalten |
|---|---|---|---|
| DR 412 | C89 |
fehlgeschlagene
#elif
-Ausdrücke mussten gültig sein
|
fehlgeschlagenes
#elif
wird übersprungen
|
Referenzen
- C23-Standard (ISO/IEC 9899:2024):
-
- 6.10.1 Bedingte Inklusion (S: TBD)
- C17-Standard (ISO/IEC 9899:2018):
-
- 6.10.1 Bedingte Übersetzung (S: 118-119)
- C11-Standard (ISO/IEC 9899:2011):
-
- 6.10.1 Bedingte Einschließung (S: 162-164)
- C99-Standard (ISO/IEC 9899:1999):
-
- 6.10.1 Bedingte Inklusion (S: 147-149)
- C89/C90 Standard (ISO/IEC 9899:1990):
-
- 3.8.1 Bedingte Einschluss
Siehe auch
|
C++ Dokumentation
für
Bedingte Einschlüsse
|