Précédent Remonter Suivant

5  Compilation conditionnelle et préprocesseur

Le préprocesseur permet de sélectionner des zones de code à compiler ou à ne pas compiler selon différentes conditions. Il est ainsi possible de tester l'existence de macros avec les directives #ifdef/#endif, et d'inclure ou non le code compris entre ces deux directives. On peut aussi tester la valeur d'une macro avec la directive #if/#endif. Ceci s'avère très utile pour fournir des programmes pouvant être compilés sur différentes architectures. Par exemple :
#if ARCH = i386
/* code pour un intel i386 */
#endif
#if ARCH = alpha
/* code pour un DEC Alpha */
#endif


Exercice 17
   Renommez la fonction factorielle() en factorielle_iterative(). Écrivez la fonction

unsigned int factorielle_recursive (unsigned int n);
qui calcule la factorielle de n de façon récursive. Placez les corps de ces fonctions dans une directive #ifdef/#endif de la manière suivante :

#ifdef RECURSIVE
unsigned int 
factorielle_recursive (unsigned int n) 
{
  ...
}

unsigned int 
factorielle (unsigned int n) 
{
  return factorielle_recursive (n);
}
#else
unsigned int 
factorielle_iterative (unsigned int n) 
{
...
}

unsigned int 
factorielle(unsigned int n) 
{
  return factorielle_iterative (n);
}
#endif
De cette manière, si la macro RECURSIVE est définie, seule la fonction factorielle_recursive() sera définie, et l'appel à la fonction factorielle() sera un appel à factorielle_recursive(). Sinon seule factorielle_iterative() est définie, et un appel à factorielle sera un appel à factorielle_iterative().

La macro RECURSIVE peut être soit définie dans le fichier source (#define RECURSIVE), soit définie au moment de la compilation grâce à l'option -D nom=definition du compilateur.

Exercice 18
   Vérifiez le travail du préprocesseur cpp en demandant au compilateur de ne faire que la phase de préprocessing :

% gcc -E -P factorielle.c 

Vous voyez apparaître les déclarations de types, variables et fonctions standard, puis celles contenues dans <stdio.h>, et enfin la définition de factorielle_iterative(), factorielle() et main().

Exercice 19
   Recommencez en définissant la macro RECURSIVE :

% gcc -E -P -D RECURSIVE factorielle.c 
C'est bien maintenant la version récursive qui est définie.

Exercice 20
   Compilez la version récursive pour étudier son comportement sous dévermineur (par exemple xxgdb, vous pouvez préférer ddd) :

% gcc -D RECURSIVE -g -Wall -Werror -ansi -pedantic -o factorielle factorielle.c
% xxgdb factorielle
  1. Placez un point d'arrêt avant le return de factorielle_recursive() et lancez l'exécution (run).
  2. Puis avancez de quelques appels récursifs (step).
  3. Vous pouvez examiner la pile des appels de fonctions avec la commande bt, et vous placer dans n'importe quel cadre d'appel par la commande frame n où n est le numéro du cadre choisi (à gauche dans l'affichage fait par bt). Par exemple,
    
    (xxgdb) print n
    $1 = 4
    (xxgdb) frame 3
    #3  0x804840d in factorielle_recursive (n=7) at factorielle.c:5
    (xxgdb) print n
    $2 = 7
    


Précédent Remonter Suivant