J'ai été programmeur Java et VB.NET pendant environ 4 ans et un programmeur C # pendant environ 6 mois. J'ai également utilisé un tas de langages dynamiques comme Perl, Python, PHP et JavaScript. P>
Je n'ai jamais eu besoin de préprocesseur. P>
Ma question est la suivante: pourquoi considérez-vous une telle utilisation étendue de préprocesseurs en C, C ++ et objectif-C mais rarement (ou jamais) le voir dans des langues comme Java, C # ou Scala? P>
12 Réponses :
Les langues modernes ont le préprocesseur inclus dans la langue elle-même! Pour C ++, le préprocesseur n'est nécessaire que pour la gestion du module et l'inclusion conditionnelle, par exemple très utile. P>
Je crois que c'était un outil séparé, car les compilateurs n'étaient pas un outil comme nous les connaissons aujourd'hui. J'ai entendu dire que de très vieux compilateurs C utilisaient les jetons vers des fichiers, puis effectuez le reste de la compilation dans des étapes séparées. La principale raison pour laquelle je puisse penser, c'est que la mémoire et les autres ressources étaient très rares par rapport à ce que nous avons aujourd'hui. P>
Vous pouvez être sûr que la langue moderne est écrite en C ou C ++, et dans cette mise en œuvre elle-même, il y a des macros. Vous avez besoin d'eux pour traiter des différences de système d'exploitation pour une chose. Les langues dynamiques / niveaux de niveau enveloppent et cachent de nombreuses choses qui ont quelque part en bas, vous avez besoin de macros pour. p>
En outre, les macros sont parfois utilisés pour la vitesse. Dans les langues dynamiques, la vitesse n'est pas aussi cruciale. p>
Le pré-processeur en C et C ++ a deux fonctions différentes p>
tirage de fichiers ensemble dans le processus de construction - langues comme Java et al. avoir leurs propres mécanismes comme l'importation pour faire cela p> li>
Effectuer des substitutions textuelles - il reste encore besoin dans une certaine mesure dans C, mais C ++ peut le faire (pour la plupart) mieux à l'aide de modèles p> li> ul>
de sorte que C et C ++ en a besoin pour le premier de ceux-ci, mais C ++ peut vous laisser tomber pour la seconde, bien qu'il puisse être utile même en C ++ - voir Cette question de plus tôt aujourd'hui. P>
certaines choses, comme à l'aide d'utiliser __ ligne __ code> et
__ fichier __ code> dans la journalisation ou les suites de test, ne peuvent pas être effectuées facilement sans le préprocesseur (et je suis triste quand je dois les faire une autre langue qui n'a pas de préprocesseur).
La raison pour laquelle vous ne voyez pas le préprocesseur utilisé dans Java, C # ou Scala est que ces langues n'en ont évidemment pas une.
L'une des utilisations courantes du prétraiteur C est d'aider à fournir une plate-forme. Code spécifique. Étant donné que c (j'inclus C ++ et l'objectif-C ici) est une langue de bas niveau qui doit être interface avec le système d'exploitation directement, dans un code portable, il doit nécessairement être des sections différentes du code compilées pour différents systèmes d'exploitation. Vous pouvez trouver de nombreux exemples de ce genre de chose dans une base de code hautement portable hautement portable telle que zlib . P> comme un exemple simple, 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 il doit exister quelque part): P>
#ifdef WIN32 closesocket(s); #else close(s); #endif
"La raison pour laquelle vous ne voyez pas le préprocesseur ... est-ce ces langues ... n'en avez pas." !! excellent!
Un vrai langage pourrait examiner la variable Win32, voir qu'il est final et générer le chemin correct en ligne. Il n'y a pratiquement aucune utilisation pour les préprocesseurs dans une langue moderne.
Ironiquement suffisamment (si je ne me trompe pas), le prédécesseur de Bjarne à C ++, C avec des classes, était essentiellement une couche de macro sur C.
Oui, l'original C ++ a été mis en œuvre comme préprocesseur. Objective-C peut toujours être un préprocesseur - et un très simple à cela. Cela ne fait pratiquement rien mais gardez une trace d'un tas de symboles et insérez des pointeurs d'adresse dans votre code.
De ce que peu j'ai lu, il semble que Bjarne soit assez adontifié que C ++ n'a jamais été mis en œuvre comme préprocesseur. C'était un compilateur entièrement formé qui généré Code C ne pas assembler. Comme Andrew mentionne, C avec des classes a apparemment été mis en œuvre comme préprocesseur.
Oui, obj-C aurait juste besoin de grep un groupe de signes et de crochets @;)
Les implémentations originales des années 1980 de C ++ étaient basées sur un prétraiteur spécial AT & T appelé CFRONT. L'arrière-plan était le compilateur C, cc. De même, la mise en œuvre d'Objective-C d'origine de StepStone, Inc (Brad Cox's Company) était un préprocesseur devant CC. Dans les deux cas, le CPP a été exécuté d'abord, puis CFRONT ou le préprocesseur de l'objectif C, puis la boîte à outils CC standard. Cela a permis à la fois que les langues soient facilement portées à de nombreuses plates-formes.
C # a un pré-déprocession: EN.CSHARP-Oronline.net/CSHARP_PRREPROCESSOR_Directives
C # Supporte #Iflubug / #endif et # région / # Endregion, mais ils ne sont pas pré-processeur i> directives.
Parce que Gosling et Heilsberg comprennent tous deux les périls et la dette technique engagée par l'utilisation abusive du prétraitement! p>
Parce que la conception et les objectifs de ces langues ne sont pas les mêmes. P>
C a été construit avec le préprocesseur à l'esprit comme un outil puissant, il a été utilisé pour mettre en œuvre des éléments très basiques (tels que des protections d'inclusion) et des développeurs ont pu l'utiliser pour optimiser leur code via des macros ou pour inclure / exclure éventuellement. certains blocs de code en plus d'autres choses. C ++ a hérité de la plupart des idiomes de C de C, les macros ne sont plus utilisées pour la vitesse (car une inline a été introduite) mais elle est toujours utilisée pour beaucoup de choses, voir le message Quelles sont les macros de préprocesseur? P>
Vous devriez regarder un peu plus près de Perl. PERL prend en charge Filtres source , qui sont essentiellement des pré-processeurs Perl personnalisés écrites dans Perl :) p>
Je ne connais pas l'objectif-c, alors ma réponse consistera à contraster l'utilisation du préprocesseur en C et C ++. P>
Le préprocesseur a été initialement nécessaire pour C pour plusieurs raisons. Si je me souviens bien, C à l'origine, c n'a pas eu de constantes, donc L'utilisation du préprocesseur en C ++ est un retour sur C et est généralement fronçonné. Les caractéristiques de la langue, telles que les constantes, les fonctions en ligne et les modèles peuvent être utilisées dans la plupart des situations où dans C, vous auriez utilisé le prétraiteur. p>
Les quelques cas où l'utilisation d'un pré-processeur en C ++ est acceptable ou même nécessaire, citons les gardes des fichiers d'en-tête, pour empêcher la même en-tête d'être incluse plusieurs fois, Le préprocesseur est également souvent utilisé pour les définitions spécifiques à la plate-forme, bien que C ++ gotchas de Stephen Dewhurst conseille avoir des annuaires distincts pour les définitions spécifiques à la plate-forme et les utiliser dans des configurations de construction distinctes pour chaque plate-forme. P> #define code> était nécessaire pour éviter les nombres magiques. Avant 1999, c n'a pas eu de fonctions intégrées, donc à nouveau
#define code> a été utilisé pour créer des macros ou des "pseudo-fonctions" pour enregistrer les frais généraux d'un appel de la fonction, tout en conservant le code structuré. C N'a pas non plus de polymorphisme de temps d'exécution ni de compilation, donc
#Ifdef code> S était nécessaire à la compilation conditionnelle. Les compilateurs n'étaient généralement pas assez intelligents pour optimiser le code inaccessible, donc encore,
#Ifdef code> S ont été utilisés pour insérer le débogage ou le code de diagnostic. P>
#Ifdef __cplusplus code> Pour utiliser la même en-tête pour C et C ++,
__ Fichier __ code> et
__ ligne __ code> pour la journalisation et quelques autres. P>
Ce n'est pas le seul temps de préprocession de temps en C ++ est considéré comme ok. Autres utilisations largement (sinon universellement) considérées correctement incluent la sortie __ fichier __ code> et
__ ligne __ code> dans la journalisation, la macro de la macro de la bulle, la vérification du compilateur (y compris le classique
#Ifdef __cplusplus // extern "c" {// #endif code>), définitions spécifiques à la plate-forme (par exemple, où vous avez besoin de
__ DeclSpec code> dans msvc et
__ attribut __ code> dans GCC), Définir Ndebug avant d'inclure
Java a été conçu pour éviter plusieurs fonctionnalités qui font du C ++ difficile à utiliser. P>
C # Copier (ou hériter) la plupart de la décision de conception de Java. P>
Langues de programmation de niveau supérieur Évitez ce type d'artefacts de niveau bas. p>
Je suis en désaccord avec ce qui semble être le consensus aller où le RPC est insatisfaisant dans les langues modernes. J'ai beaucoup de cas où j'ai 3 versions légèrement différentes du même programme, et je veux pouvoir faire un tas de modifications pour chaque version. Avec CPP, je peux les mettre tous dans #idif #else blocs, et je peux définir le #idif à la ligne de compilation. En Java, j'ai besoin de créer une sorte de Statique globale et de l'initialiser à la compilation. Je n'ai jamais obtenu cela pour fonctionner correctement. P>
@Brian: eww! Je ne suis pas surpris que cela ne fonctionnait pas correctement! Une meilleure solution en Java serait d'utiliser des sous-classes ou du modèle "Stratégie" pour séparer les différences entre les versions.
Mais si les différences sont à 10 lignes éparpillées à travers une classe ou pire plusieurs classes? C'est beaucoup d'efforts.
@Brian: Vous ne pouvez pas gagner cet argument. C'est Java, alors plus de classes => mieux ;-)
Chaque langue a besoin d'un mécanisme pour compilation séparée forte>. Idéalement, la langue distingue les interfaces des implémentations et un module ne dépend que des interfaces des modules qu'il exporte. (Voir, E.G., ADA, CLU, MOTILA, SO SO.) P>
c n'a pas de construction de langue pour des interfaces ou des implémentations. Parce qu'il est essentiel que différents fichiers .c partagent une seule vue d'interfaces, la discipline de programmation a évolué de mettre des déclarations (c.-à-d. Des interfaces) dans .h Fichiers et partageant ces déclarations / interfaces à l'aide de l'inclusion textuelle ( De nos jours Les concepteurs de langue reconnaissent que l'inclusion textuelle n'est pas un moyen de faire fonctionner un chemin de fer, des langues ont donc tendance à exécuter soit à des interfaces compilées séparément (ADA, MODULA, OCAML), aux interfaces générées par compilateur (HASKELL) ou à des systèmes dynamiques que garantir la cohérence de l'interface (Java, SmallTalk). Avec un tel mécanisme, il n'est pas nécessaire de préprocesseur et de nombreuses raisons de ne pas avoir une (penser analyse de code source em> et débogage em>). P> #include code> ). En principe,
#define code> et
#Ifdef code> pourrait être distribué avec, mais
#include code> ne pouvait pas. P>
+1 Votre réponse semble être la plus neutre et l'informative ici. Je vous applaudis.
Je pense que #if code> et des amis sont toujours nécessaires pour le code spécifique de la plate-forme en C / C ++.
Le prétraitement est très, très courant dans le monde de Java. Il est utilisé pour compenser le manque d'installations d'abstraction intégrées de la langue, ce qui conduirait autrement à un code de chaudras copié et collé sans fin. P>
La raison de nombreuses personnes ne réalisent pas que cela est vrai, c'est que, dans le monde de Java, il s'appelle "génération de code" plutôt que "prétraitement", car "le prétraitement" sonne comme un vieux vieux C, tandis que "la génération de code" sonne comme un outil professionnel qui efficace les processus d'entreprise mature. Il s'agit toujours de prétraitement, même si vous devez payer une fortune pour un outil propriétaire non standard incompatible pour le faire, au lieu d'utiliser simplement des installations intégrées à la langue. P>
Quelle réponse brillante, j'aimerais vraiment pouvoir lui donner plus d'un vote en up!
Yup, parfois, je manque vraiment le préprocesseur lors de l'utilisation de Java
Nous avons appris de C / C ++ / Objective-C, ils ont obtenu le compilateur C à droite alors juste construits sur le dessus, car il était plus facile de cette façon. Les langues plus récentes ont été viennent de mieux conçues de la terre. La plupart des gens que je connais avec une expérience C qui sont passés sont terrifiés de pré-processeurs. Pas bon pour la vitesse, vissait votre conception, nuit à la compréhension. Aucun avantage sauf que cela vous permet d'écrire un code pire - pourquoi quelqu'un voudrait-il copier cela exprès?
Voir stackoverflow.com/questions/652788/... et blogs.msdn.com/oldnewthing/archive/2005/01/06/347666.aspx :)
J'ai plusieurs programmes DSP C ++ lorsque chaque cycle compte (oui, vraiment). Le préprocesseur me aide beaucoup pendant l'optimisation. Je ne l'utilise pas pour autre chose. Je l'aime. Vous ne pouviez pas le prier de mes mains. Avez-vous fait beaucoup de programmation DSP en temps réel dans ces langages dynamiques? N'oubliez pas que peu importe le nombre de types de programmation que vous avez faite, vous avez juste gratté la surface des types de programmation que peut faire i>.
@Nosredna: Oh, je suis tout à fait d'accord pour dire que, juste parce que je n'ai pas eu besoin de préprocesseur, je n'en aurais jamais besoin. J'étais juste curieux quant à la raison pour laquelle vous le voyez d'utiliser beaucoup plus dans les langues C et C-Superset.
Personnellement, j'aime vraiment le préprocesseur des tests C / C ++. Je trouve que c'est vraiment facile d'écrire / d'étendre une suite de test à l'aide du préprocesseur que de faire des choses similaires dans d'autres langues. Je manque personnellement le préprocesseur lors de l'utilisation d'autres langues. (Bien sûr, cela, en utilisant
__ fichier __ / __ ligne __ code> dans la journalisation et la compilation conditionnelle concerne uniquement les seuls moments que je dois utiliser le pré-processeur.)
Je devrais aussi souligner que c # a quelque chose de similaire au pré-processeur C: docs.microsoft.com/en-us/dotnet/cshaarp/language-référence/... . Bien que plus limitée.