Préprocesseur - Définition

Source: Wikipédia sous licence CC-BY-SA 3.0.
La liste des auteurs de cet article est disponible ici.

Introduction

En informatique, un préprocesseur est un programme qui procède à des transformations sur un code source, avant l'étape de compilation (on parle alors de pré-compilateur) ou d'interprétation proprement dite. Les préprocesseurs sont des exemples typiques de langages spécialisés.

Pré-processeurs lexicaux

Les préprocesseurs lexicaux sont les préprocesseurs de plus bas niveau, au sens où ils requièrent uniquement un mécanisme d'analyse lexicale. Ces préprocesseurs se contentent de procéder à des substitutions de chaînes de caractères en fonction de règles définies par l'utilisateur. On les utilise généralement pour instancier des macros, inclure d'autres fichiers (par opposition à des fonctionnalités de plus haut niveau telles que l'inclusion de modules/paquets/unités/composants) et permettre la compilation ou/et l'inclusion conditionnelle.

Pré-processeur C/C++

Le préprocesseur le plus utilisé est C PreProcessor (CPP) ; il est employé à chaque étape dans le monde C/C++.

Inclusion

L'usage le plus fréquent du préprocesseur C est la directive

      #include "…"      

ou

      #include <…>      

dont le rôle est de recopier le contenu d'un fichier dans le fichier courant. On l'emploie généralement pour inclure les en-têtes de bibliothèques, telles que les fonctions mathématiques () ou les fonctions d'entrée/sortie standard ().

Si cet usage du préprocesseur permet d'ajouter à moindre coût la réutilisation de code à un langage de programmation, il s'agit d'une technique lente, inefficace, et qui nécessite l'ajout manuel de directives de compilation conditionnelle pour éviter d'inclure et de compiler plusieurs fois un fichier d'en-tête.

Depuis les années 1970, des alternatives plus rapides, plus sûres et plus efficaces sont connues et employées dans la majorité des langages de programmation : Java comporte des paquets, Pascal des unités, Modula, OCaml, Haskell ou Python des modules. De même, le langage D, conçu comme remplacement de C et C++ a des « importations » (NB : à la connaissance du rédacteur de cet article, le terme n'a pas encore de traduction officielle).

Macros

Le mécanisme des macros est fréquemment utilisé en C pour définir de petits extraits de code qui seront réutilisés à divers endroits du programme. Durant l'exécution du préprocesseur, chaque appel de la macro est remplacé, dans le corps du fichier, par la définition de cette macro.

Exemple :

      #define max(a,b) a>b?a:b      

définit la macro max. Cette macro peut être appelée comme n'importe quelle fonction C. Ainsi, après passage du préprocesseur,

      z = max(x,y);      

devient

      z = x>y?x:y;      

Cet usage des macros est fondamental en C, notamment pour définir des structures de données sûres ou en tant qu'outil de débogage, il ralentit la compilation et parfois l'exécution, et présente de nombreux pièges.

Ainsi, contrairement à l'intuition, si f et g sont deux fonctions, l'appel

      z = max(f(), g());      

ne se contentera pas d'évaluer f() et g() et de placer le plus haut des résultats dans z. En fait, l'une des deux fonctions sera évaluée deux fois. Si cette fonction a des effets de bord, ceci n'est généralement pas le comportement attendu.

Les langages de programmation plus modernes se passent généralement de méta-programmation par macro-expansion de chaînes de caractères, et utilisent généralement des fonctions/méthodes traditionnelles, recopiées par le compilateur en ligne en fonction d'optimisations automatiques ou guidées. De même, plutôt que d'utiliser des macros pour définir des structures de données, ces langages utilisent souvent du polymorphisme paramétrique (aussi appelé templates, alias méthodes/classes génériques).

Les langages Lisp, cependant, sont intégralement conçus autour d'une utilisation similaire des macros, mais à l'aide de techniques bien plus puissantes.

Compilation conditionnelle

Le préprocesseur C permet aussi la compilation conditionnelle, ce qui permet de disposer de plusieurs versions d'un même programme ou d'un extrait dans un même fichier source. Typiquement, les programmeurs C utilisent cette technique pour pouvoir compiler différemment le programme en fonction de son état d'avancement, de la plateforme de destination, des tests désirés, ou pour s'assurer que les fichiers d'en-tête ne sont inclus qu'une seule fois.

      #ifdef x       …      #else       …      #endif      

ou

      #if x       …      #else       …      #endif      

La majorité des langages de programmation modernes n'utilisent pas cette fonctionnalité et dépendent plutôt d'une utilisation des habituels opérateurs if…then…else…, laissant au compilateur la tâche de supprimer le code inutile.

Autres pré-processeurs lexicaux

  • Le langage généraliste m4 est utilisé essentiellement dans la conception de systèmes de compilation multiplate-forme.
  • Le langage généraliste php (Hypertext Preprocessor) est utilisé essentiellement pour la conception de sites web.
Page générée en 0.094 seconde(s) - site hébergé chez Contabo
Ce site fait l'objet d'une déclaration à la CNIL sous le numéro de dossier 1037632
A propos - Informations légales
Version anglaise | Version allemande | Version espagnole | Version portugaise