Conditional inclusion
Le préprocesseur prend en charge la compilation conditionnelle de parties du fichier source. Ce comportement est contrôlé par les directives
#if
,
#else
,
#elif
,
#ifdef
,
#ifndef
,
#elifdef
,
#elifndef
(depuis C23)
, et
#endif
.
Table des matières |
Syntaxe
#if
expression
|
|||||||||
#ifdef
identifiant
|
|||||||||
#ifndef
identifiant
|
|||||||||
#elif
expression
|
|||||||||
#elifdef
identifiant
|
(depuis C23) | ||||||||
#elifndef
identifiant
|
(depuis C23) | ||||||||
#else
|
|||||||||
#endif
|
|||||||||
Explication
Le bloc de prétraitement conditionnel commence par la directive
#if
,
#ifdef
ou
#ifndef
, inclut ensuite optionnellement un nombre quelconque de directives
#elif
,
#elifdef
, ou
#elifndef
(depuis C23)
, inclut optionnellement au plus une directive
#else
et se termine par la directive
#endif
. Tout bloc de prétraitement conditionnel interne est traité séparément.
Chacune des directives
#if
,
#ifdef
,
#ifndef
,
#elif
,
#elifdef
,
#elifndef
(depuis C23)
, et
#else
contrôle un bloc de code jusqu'à la première directive
#elif
,
#elifdef
,
#elifndef
(depuis C23)
,
#else
,
#endif
n'appartenant à aucun bloc de prétraitement conditionnel interne.
#if
,
#ifdef
et
#ifndef
testent la condition spécifiée (voir ci-dessous) et si elle est évaluée à vrai, compilent le bloc de code contrôlé. Dans ce cas, les directives suivantes
#else
,
#elifdef
,
#elifndef
,
(depuis C23)
et
#elif
sont ignorées. Sinon, si la condition spécifiée est évaluée à faux, le bloc de code contrôlé est ignoré et la directive suivante
#else
,
#elifdef
,
#elifndef
,
(depuis C23)
ou
#elif
(le cas échéant) est traitée. Si la directive suivante est
#else
, le bloc de code contrôlé par la directive
#else
est compilé inconditionnellement. Sinon, la directive
#elif
,
#elifdef
, ou
#elifndef
(depuis C23)
agit comme s'il s'agissait d'une directive
#if
: vérifie la condition, compile ou ignore le bloc de code contrôlé en fonction du résultat, et dans ce dernier cas traite les directives suivantes
#elif
,
#elifdef
,
#elifndef
,
(depuis C23)
et
#else
. Le bloc de prétraitement conditionnel est terminé par la directive
#endif
.
Évaluation conditionnelle
#if, #elif
L' expression est une expression constante, utilisant uniquement des constantes et des identifiants, définis à l'aide de la directive #define . Tout identifiant, qui n'est pas littéral, non défini à l'aide de la directive #define , s'évalue à 0 sauf true qui s'évalue à 1 (depuis C23) .
L'expression peut contenir des opérateurs unaires sous la forme
defined
identifiant
ou
defined (
identifiant
)
qui renvoient
1
si l'
identifiant
a été défini en utilisant la directive
#define
et
0
sinon.
Dans ce contexte,
__has_include
,
__has_embed
et
__has_c_attribute
sont traités comme s'ils étaient des noms de macros définies.
(depuis C23)
Si l'
expression
s'évalue à une valeur non nulle, le bloc de code contrôlé est inclus et ignoré sinon. Si un identifiant utilisé n'est pas une constante, il est remplacé par
0
.
|
Dans le contexte d'une directive de préprocesseur, une expression
|
(depuis C23) |
Note : Jusqu'à
DR 412
,
#if
cond1
...
#elif
cond2
diffère de
#if
cond1
...
#else
suivi de
#if
cond3
car si
cond1
est vrai, le second
#if
est ignoré et
cond3
n'a pas besoin d'être bien formé, tandis que
#elif
nécessite que
cond2
soit une expression valide. Depuis
DR 412
,
#elif
qui précède un bloc de code ignoré est également ignoré.
Directives combinées
Vérifie si l'identificateur a été défini comme nom de macro .
#ifdef
identifier
est essentiellement équivalent à
#if defined
identifier
.
#ifndef
identifier
est essentiellement équivalent à
#if !defined
identifier
.
|
|
(depuis C23) |
Notes
Bien que
#elifdef
et
#elifndef
ciblent C23, les implémentations peuvent les rétroporter vers les modes de langage plus anciens en tant qu'extensions conformes.
Exemple
#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"); // sélectionné en mode C23, peut être sélectionné en mode pré-C23 #else printf("4: no3\n"); // peut être sélectionné en mode pré-C23 #endif }
Sortie possible :
1: yes 2: yes 3: yes 4: yes
Rapports de défauts
Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C publiées antérieurement.
| DR | Appliqué à | Comportement publié | Comportement corrigé |
|---|---|---|---|
| DR 412 | C89 |
l'expression d'un
#elif
échoué devait être valide
|
un
#elif
échoué est ignoré
|
Références
- Norme C23 (ISO/CEI 9899:2024) :
-
- 6.10.1 Inclusion conditionnelle (p: À DÉTERMINER)
- Norme C17 (ISO/CEI 9899:2018):
-
- 6.10.1 Inclusion conditionnelle (p: 118-119)
- Norme C11 (ISO/CEI 9899:2011) :
-
- 6.10.1 Inclusion conditionnelle (p: 162-164)
- Norme C99 (ISO/IEC 9899:1999) :
-
- 6.10.1 Inclusion conditionnelle (p: 147-149)
- Norme C89/C90 (ISO/IEC 9899:1990) :
-
- 3.8.1 Inclusion conditionnelle
Voir aussi
|
Documentation C++
pour
Inclusion conditionnelle
|