Next: Récréation
Up: Le préprocesseur
Previous: Traitement de macros
Sous-sections
Les mécanismes de compilation conditionnelles ont pour but de compiler
ou d'ignorer des ensembles de lignes, le choix étant basé sur un test
exécuté à la compilation.
La commande permettant de réaliser la compilation conditionnelle est la
commande
#if qui peut prendre plusieurs formes.
Quand le préprocesseur rencontre :
#if
expression
ensemble-de-lignes
#endif
il évalue
expression.
Si
expression délivre une valeur non nulle,
ensemble-de-lignes
est compilé, sinon
ensemble-de-lignes est ignoré.
L'évaluation de
expression a lieu au moment de la compilation,
elle ne doit donc comporter que des constantes.
L'
ensemble-de-lignes est une suite de lignes quelconques.
Sur rencontre de :
#if
expression
ensemble-de-lignes1
#else
ensemble-de-lignes2
#endif
le préprocesseur évalue
expression.
Si
expression délivre une valeur non nulle,
ensemble-de-lignes1 est compilé
et
ensemble-de-lignes2 est ignoré, sinon
ensemble-de-lignes1 est ignoré
et
ensemble-de-lignes2 est compilé.
De manière à imbriquer aisément des
#if
dans des
#if
, il existe
une commande
#elif
dont la sémantique est else if.
Elle s'utilise de la manière suivante :
#if
expression1
ensemble-de-lignes1
#elif
expression2
ensemble-de-lignes2
...
#elif
expressionn
ensemble-de-lignesn
#else
ensemble-de-ligneselse
#endif
Un seul
ensemble-de-lignes sera compilé : celui correspondant à la
première
expressioni qui s'évaluera à une valeur non nulle si
elle existe, ou bien
ensemble-de-ligneselse
si toutes les
expressioni s'évaluent à 0.
Dans ce qui précède il est possible de remplacer les commandes
#if
expression par :
#ifdef
nom ou
#ifndef
nom.
Dans ce cas, le test ne porte plus sur la nullité ou non d'une expression, mais
sur la définition ou non d'une macro.
La commande
#ifdef
nom a pour sémantique :
<< si
nom est défini >>, et
#ifndef
nom
a pour sémantique : << si
nom n'est pas défini >>.
L'opérateur
defined est un opérateur spécial : il ne peut être
utilisé que dans le contexte d'une commande
#if
ou
#elif
.
Il peut être utilisé sous l'une des deux formes suivantes :
defined
nom ou bien :
defined ( nom ).
Il délivre la valeur 1 si
nom est une macro définie, et la valeur 0
sinon.
L'intérêt de cet opérateur est de permettre d'écrire des tests portant
sur la définition de plusieurs macros, alors que
#ifdef ne peut en
tester qu'une.
#if defined(SOLARIS) || defined(SYSV)
La commande
#error a la syntaxe suivante :
#error
suite-d-unités-lexicales
La rencontre de cette commande provoquera l'émission d'un message d'erreur
comprenant la
suite-d-unités-lexicales.
Cette commande a pour utilité de capturer à la compilation des conditions
qui font que le programme ne peut pas s'exécuter sur cette plate-forme.
Voici un exemple où on teste que la taille des entiers est suffisante :
#include <limits.h>
#if INT_MAX < 1000000
#error "Entiers trop petits sur cette machine"
#endif
Usage
La compilation conditionnelle a pour but essentiel d'adapter le programme
à son environnement d'exécution : soit il s'agit d'un programme système
devant s'adapter au matériel sur lequel il s'exécute, soit il s'agit d'un
programme d'application qui doit s'adapter au système sur lequel il s'exécute.
Prenons par exemple le système
UNIX qui existe en deux grandes
variantes : la variante
BSD et la variante
SYSTEM V.
La routine de recherche d'un caractère déterminé dans une chaîne s'appelle
index en
BSD et
strchr en
SYSTEM V, mais l'interface
est le même.
Voici comment on peut écrire un programme se compilant et s'exécutant sur les
deux plate-formes : le programmeur peut décider d'utiliser un nom à lui,
par exemple RechercheCar, et de le définir comme ci-dessous.
#if defined(HAS_INDEX)
#define RechercheCar index
#elif defined(HAS_STRCHR)
#define RechercheCar strchr
#else
#error "Impossible de réaliser RechercheCar"
#endif
Selon le système, la compilation se fera par :
cc -c -DHAS_INDEX fichier.c
ou par :
cc -c -DHAS_STRCHR fichier.c
Next: Récréation
Up: Le préprocesseur
Previous: Traitement de macros
Bernard Cassagne
1998-12-09