Préprocesseur - Définition

Source: Wikipédia sous licence CC-BY-SA 3.0.
La liste des auteurs est disponible ici.
image:Langage_progr.png
Langages à objets
C++ - C# - D
Delphi - Eiffel - Groovy
Java - Lisaac - Python - Ruby
Simula - Smalltalk
Visual Basic - WLangage
Langages impératifs
APL - ASP - Assembleur
BASIC - C - Cobol - Natural
Forth - Fortran - Limbo
Logo - Pascal - Perl - PHP
Langages fonctionnels
Haskell - ML/OCaml
Lisp/Common Lisp
Scheme - XSLT
Langages déclaratifs
Clips - Prolog
Langages concurrents
Ada 95 - Erlang
Voir aussi
Conception - Codage
Tests - Optimisations

En informatique, un préprocesseur est un programme qui procède à des transformations sur un code source, avant l'étape de compilation 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 CPP, pour C PreProcessor, qui 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

or

#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.

Préprocesseurs syntaxiques

La notion de préprocesseur syntaxique a été introduite avec le langage Lisp. Son rôle est de transformer des arbres de syntaxe en fonction de règles définies par l'utilisateur. Pour certains langages de programmation, ces règles sont écrites dans le même langage que le programme (introspection statique). C'est le cas de Lisp ou d'OCaml. Dans d'autres cas, il s'agit d'un langage externe entièrement, tel que XSLT pour XML, ou de sa contrepartie statiquement typée CDuce.

Les préprocesseurs syntaxiques sont typiquement utilisés pour personnaliser la syntaxe d'un langage, pour étendre un langage avec de nouvelles primitives ou pour transformer un langage de programmation généraliste en un langage spécialisé.

Personnalisation de la syntaxe

Un bon exemple de personnalisation de syntaxe est l'existence de deux syntaxes distinctes pour le langage OCaml. Un programme peut être écrit indifféremment à l'aide de la " syntaxe normale " ou de la " syntaxe révisée ", et peut être réaffiché à la demande dans une syntaxe ou l'autre.

De même, un grand nombre de programmes écrits en OCaml personnalisent la syntaxe du langage pour lui ajouter de nouveaux opérateurs.

Extension d'un langage

Le meilleur exemple d'extension d'un langage à l'aide de macros est Lisp. Alors que les langages de la famille, par eux-mêmes, ne sont que des noyaux fonctionnels minimalistes (moins de 10 instructions) et dynamiquement typés, la distribution standard de Scheme ou de Common Lisp permet la programmation impérative ou orientée objets, ou encore le typage statique. Toutes ces fonctionnalités sont implantées à l'aide du préprocesseur syntaxique.

De la même manière, la gestion d'expressions rationnelles ou la génération de code statiquement vérifiées et fortement typées peuvent être ajoutées à la syntaxe et la sémantique d'OCaml à l'aide de macros, de même que des fibres (ou coroutines, ou générateurs), des monades ou la manipulation transparente d'arbres XML.

Specialisation d'un langage

Une fonctionnalité inhabituelle de Lisp est la possibilité d'utiliser des macros pour transformer le langage en un langage spécialisé. Typiquement, dans tout projet Lisp suffisamment large, une partie de l'effort est concentré sur l'adaptation du langage lui-même à la tâche visée, et la construction, par exemple, de dialectes pour SQL ou pour l'affichage ou l'interface graphique, etc. D'après des programmeurs Lisp expérimentés, cette fonctionnalité leur permet de diviser par 7 à 20 fois le temps et la longueur du code nécessaire pour achever un projet.

Le préprocesseur MetaOCaml fournit des fonctionnalités similaires pour la conception de langages spécialisés externes. Ce préprocesseur, à partir de la description de la sémantique d'un langage (i.e. un interpréteur), à l'aide d'interprétation durant la compilation et de génération de code, convertit cette description en un compilateur dans le langage Ocaml.

Page générée en 0.102 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 | Partenaire: HD-Numérique
Version anglaise | Version allemande | Version espagnole | Version portugaise