11 votes

Pourquoi l'utilisation du préprocesseur est-elle moins courante dans les langages autres que C/C++/ObjC ?

J'ai été programmeur Java et VB.Net pendant environ 4 ans et programmeur C# pendant environ 6 mois. J'ai également utilisé un certain nombre de langages dynamiques comme Perl, Python, PHP et JavaScript.

Je n'ai jamais eu besoin d'un préprocesseur.

Ma question est la suivante : pourquoi voit-on une telle utilisation des préprocesseurs en C, C++ et Objective-C mais rarement (ou jamais) dans des langages comme Java, C# ou Scala ?

14voto

Dima Points 19888

Je ne connais pas l'Objective-C, donc ma réponse consistera à comparer l'utilisation du préprocesseur en C et C++.

Le préprocesseur était à l'origine nécessaire pour le C pour plusieurs raisons. Si je me souviens bien, à l'origine le C n'avait pas de constantes, donc #define était nécessaire pour éviter les chiffres magiques. Avant 1999, le C n'avait pas de fonctions en ligne, donc encore une fois #define a été utilisé pour créer des macros ou des "pseudo-fonctions" afin d'économiser la surcharge d'un appel de fonction, tout en gardant le code structuré. Le C ne dispose pas non plus de polymorphisme au moment de l'exécution ou de la compilation. #ifdef s étaient nécessaires pour la compilation conditionnelle. Les compilateurs n'étaient généralement pas assez intelligents pour optimiser le code inaccessible, donc, encore une fois, #ifdef ont été utilisés pour insérer du code de débogage ou de diagnostic.

L'utilisation du préprocesseur en C++ est un retour en arrière vers le C, et est généralement désapprouvée. Les caractéristiques du langage, telles que les constantes, les fonctions en ligne et les modèles, peuvent être utilisées dans la plupart des situations où, en C, vous auriez utilisé le préprocesseur.

Les quelques cas où l'utilisation d'un préprocesseur en C++ est acceptable ou même nécessaire incluent les gardes pour les fichiers d'en-tête, afin d'éviter que le même en-tête soit inclus plusieurs fois, #ifdef __cplusplus d'utiliser le même en-tête pour le C et le C++, __FILE__ y __LINE__ pour l'exploitation forestière, et quelques autres.

Le préprocesseur est également souvent utilisé pour les définitions spécifiques à la plate-forme, bien que Les pièges du C++ Stephen Dewhurst conseille d'avoir des répertoires d'inclusion séparés pour les définitions spécifiques à la plate-forme, et de les utiliser dans des configurations de construction séparées pour chaque plate-forme.

11voto

Greg Hewgill Points 356191

La raison pour laquelle vous ne voyez pas le préprocesseur utilisé en Java, C# ou Scala est que ces langages n'en ont évidemment pas.

L'une des utilisations courantes du préprocesseur C consiste à fournir du code spécifique à la plate-forme. Comme le C (j'inclus ici le C++ et l'Objective-C) est un langage de bas niveau qui doit s'interfacer directement avec le système d'exploitation, dans un code portable, il doit nécessairement y avoir différentes sections du code compilées pour différents systèmes d'exploitation. Vous pouvez trouver de nombreux exemples de ce genre de choses dans une base de code mature et hautement portable telle que zlib .

Par exemple, pour fermer une prise réseau, il faut faire quelque chose comme ceci (à un certain niveau, cela peut certainement être enveloppé dans une fonction, mais cela doit exister quelque part) :

#ifdef WIN32
    closesocket(s);
#else
    close(s);
#endif

Les langages plus récents qui s'exécutent sur des machines virtuelles n'ont pas besoin des différentes sections de code spécifiques à la plate-forme et peuvent être écrits avec la bibliothèque standard unique et portable.

Le préprocesseur fournit également un moyen de définir des constantes en C, qui sont fournies par d'autres fonctionnalités du langage, meilleures, dans des langages plus récents.

Dans The Design and Evolution of C++, Bjarne Stroustrup a déclaré qu'il voulait supprimer la dépendance au préprocesseur dans le C++, mais qu'il n'y est pas parvenu.

9voto

Norman Ramsey Points 115730

Chaque langue a besoin d'un mécanisme pour compilation séparée . Idéalement, le langage distingue les interfaces des implémentations, et un module ne dépend que des interfaces des modules qu'il exporte. (Voir, par exemple, Ada, Clu, Modula, et ainsi de suite).

Le langage C n'a pas de construction pour les interfaces ou les implémentations. Étant donné qu'il est essentiel que différents fichiers .c partagent une vision unique des interfaces, la discipline de programmation a évolué pour placer les déclarations (c'est-à-dire les interfaces) dans des fichiers .h et partager ces déclarations/interfaces en utilisant l'inclusion textuelle ( #include ). En principe, #define y #ifdef pourrait être supprimée, mais #include ne pouvait pas.

De nos jours, les concepteurs de langage reconnaissent que l'inclusion textuelle n'est pas un moyen de faire fonctionner un chemin de fer. Les langages ont donc tendance à fonctionner soit avec des interfaces compilées séparément (Ada, Modula, OCaml), soit avec des interfaces générées par le compilateur (Haskell), soit avec des systèmes dynamiques qui garantissent la cohérence des interfaces (Java, Smalltalk). Avec un tel mécanisme, il n'y a pas besoin d'un préprocesseur, et de nombreuses raisons de ne pas en avoir (pensez à analyse du code source y Débogage ).

4voto

Diaa Sami Points 1802

Parce que la conception et les objectifs de ces langues ne sont pas les mêmes.

Le C a été construit avec le préprocesseur à l'esprit comme un outil puissant, il a été utilisé pour mettre en œuvre des choses très basiques (comme les gardes d'inclusion) et les développeurs ont pu l'utiliser pour optimiser leur code par le biais de macros ou pour inclure/exclure optionnellement certains blocs de code en plus d'autres choses. Le C++ a hérité de la plupart des idiomes du C, les macros ne sont plus utilisées pour la vitesse (parce que l'inline a été introduit) mais il est encore utilisé pour beaucoup de choses, voir le post À quoi servent les macros du préprocesseur ?

3voto

rp. Points 9997

Parce que Gosling et Heilsberg comprennent tous deux les périls et la dette technique encourus par l'utilisation abusive du prétraitement !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X