Programmation C
Prépocesseur
Cours Exercices Correction des exercices

Définition #include #define
#if, #endif, #elif, #else #ifdef, #ifndef #pragma once

Définition

  • Préprocesseur : Programme exécuté avant la compilation sur le ou les fichiers de code source permettant de définir ce qui doit être compilé ou non
    • Parties à compiler
    • Parties à ne pas compiler
    • Parties à substituer avec d'autres parties
  • Existence de directives permettant d'indiquer au préprocesseur ce qu'il doit faire
  • Directives caractérisées par le fait de commencer par un #
    • #include
    • #define
    • #if
    • #endif
    • #else
    • #elif
    • #ifdef
    • #ifndef
    • #pragma
  • Directives utilisables n'importe où dans le code source en dehors de toute considération relative à la structuration du code (fonctions, while, for, if, switch...) car il ne s'agit pas de code source stricto sensu
    Attention à la possibilité de compiler le résultat de l'exécution du préprocesseur
  • Utilité
    • Définition de constantes
    • Inclusion de code source annexe (en particulier stocké dans des fichiers annexes)
      • Déclarations
      • ...
    • Compilation différenciée
      • Gestion de plateforme
        • Linux ou Windows
        • 32 bits ou 64 bits
        • Version "release" ou version "debug"
        • ...
      • Gestion de version
      • ...

#include

  • Inclusion d'un fichier annexe dans le code source (généralement un fichier header d'extension .h)
  • Syntaxes
    #include <nomFichier>
    Inclusion d'un fichier à chercher dans les répertoires "include" prédéfinis pour le compilateur ou par la commande de compilation
    #include "nomFichier"
    Inclusion d'un fichier à chercher dans le répertoire qui contient le fichier .c en train d'être compilé, puis dans les répertoires "include" prédéfinis pour le compilateur ou par la commande de compilation
  • Exemples
    • #include <stdio.h>
      Inclusion du fichier d'entête stdio.h contenant les déclarations liées à l'API standard stdio
    • #include "rectangle.h"
      Inclusion du fichier d'entête rectangle.h qui décrit probablement une API non standard
  • Possibilité d'indiquer un fichier par un nom en localisation absolue (pas recommandé) ou en localisation relative (pas recommandé non plus)
  • Privilégier l'indication de répertoires spécifiques contenant les fichiers .h via paramètrage de la commande de compilation
  • Voir le chapitre "Modularité" pour l'utilisation du #include dans le cadre de l'écriture d'un programme composé de plusieurs fichiers de code source

#define

  • Définition d'une macro
  • Macro : association entre un identificateur et une chaîne de substitution (éventuellement vide)
    • Macro vide
      • Syntaxe
        #define NOM_IDENTIFICATEUR
    • Macro constante
      • Syntaxe
        #define NOM_IDENTIFICATEUR expression
    • Macro paramètrable
      • Syntaxe
        #define NOM_IDENTIFICATEUR(var1, var2,..., varN) expression
        où expression utilise les "paramètres" var1 à varN
  • Si macro vide, simple définition d'un nom dont on peut tester l'existence (voir plus loin)
  • Si macro non vide, substitution de tous les NOM_IDENTIFICATEUR par l'expression
    • "Vrai" code inséré et compilé et pas référence à une variable ou à un appel à une fonction
    • Substitution pouvant être générique (voir exemple ci-dessous) c'est à dire compatible avec des paramètres de différents types
  • Exemple
  • #include <stdio.h>

    #define FLAG
    #define PI 3.14159
    #define CONTINENT_1 "Oceanie"
    #define MAX(a,b) ((a>b) ? a : b)

    void main(void) {
      printf("%lf\n",PI);
      printf("%s\n", CONTINENT_1);
      printf("%d\n", MAX(3, 1));
      printf("%d\n", MAX(2, 6));
      printf("%lf\n", MAX(3.5, 1.8));
      printf("%lf\n", MAX(-2.6, 7.8));
    }

    PreprocesseurDefine.c - PreprocesseurDefine.exe
    • Définition d'une macro vide (FLAG)
    • Définition de deux macros constantes (PI et CONTINENT_1)
    • Définition d'une macro paramétrée générique à deux "paramètres" (MAX)
    3.141590
    Oceanie
    3
    6
    3.500000
    7.800000
  • Possibilité de passer des macro vides par l'intermédiaire de la commande de compilation

#if, #endif, #elif, #else

  • Compilation conditionnelle
  • Modalités d'utilisation similaires à celles du if du langage C mais pour définir les portions de code qui seront compilées ou non
  • Syntaxe
    #if condition
    ...
    #endif
  • Syntaxe
    #if condition
    ...
    #else
    ...
    #endif
  • Syntaxe
    #if condition1
    ...
    #elif condition2
    ...
    #else
    ...
    #endif
  • Port de #if et de #elif sur une condition
    • Opérateurs =, >, >=, <, <=, !=, !, &&, || pouvant porter sur les macros constantes entières ou des constantes entières
    • Existence de la fonction de test defined(MACRO) permettant de savoir si une macro existe
  • Exemple
  • #include <stdio.h>

    #define DEBUG
    #define PLATEFORME 99
    #define VERSION 3

    void main(void) {
    #if defined(DEBUG)
      printf("Debug\n");
    #endif
    #if defined(PLATEFORME)
      printf("Plateforme %d\n",PLATEFORME);
    #else
      printf("Plateforme non definie\n");
    #endif
    #if VERSION >= 4
      printf("Version superieure a 4\n");
    #elif VERSION == 3
      printf("Version 3\n");
    #else
      printf("Version inferieure a 3\n");
    #endif
    }

    PreprocesseurIf.c - PreprocesseurIf.exe
    • Définition d'une macro vide (DEBUG)
    • Définition de deux macros constantes (PLATEFORME et VERSION)
    • Test de l'existence de la macro DEBUG pour faire un printf
    • Test de l'existence de la macro PLATEFORME pour n'afficher sa valeur que si elle existe
    • Tests de la valeur de la macro VERSION pour afficher un message contextualisé
    Debug
    Plateforme 99
    Version 3

#ifndef, #ifdef

  • Possibilité de tester directement l'existence ou l'absence de la définition d'une macro
  • Syntaxe
    #ifdef MACRO
    ...
    #endif
  • Syntaxe
    #ifndef MACRO
    ...
    #endif
  • Exemple
  • #include <stdio.h>

    #define DEBUG

    #ifndef PLATEFORME
    #define PLATEFORME 100
    #endif

    #ifdef PLATEFORME
    void affichageVersion(int version) {
      printf("Plateforme %d\n",PLATEFORME);
    }
    #endif

    void main(void) {
    #ifdef DEBUG
      printf("Debug\n");
    #endif
    #ifdef PLATEFORME
      affichageVersion(PLATEFORME);
    #endif
    }

    PreprocesseurIfdefIfndef.c - PreprocesseurIfdefIfndef.exe
    • Définition d'une macro vide (DEBUG)
    • Définition d'une macro constante (PLATEFORME) si elle n'existe pas déjà
    • Utilisation de la macro PLATEFORME pour compiler ou non la fonction affichageVersion si PLATEFORME est définie quelle que soit sa valeur
    • Exécution de la fonction affichageVersion dans la fonction main si PLATEFORME est définie quelle que soit sa valeur
    Debug
    Plateforme 100

#pragma once

  • Voir chapitre Modularité