Quand est-ce que la compilation conditionnelle est une bonne idée et quand est-ce une idée horriblement mauvaise? p>
Par compilation conditionnelle Je veux dire avec #Ifdef code> S pour compiler uniquement certains bits de code dans certaines conditions. Le
#definefind code> S peut-être dans un fichier d'en-tête commun ou introduit via la directive
-d code> compilateur. P>
8 Réponses :
C'est toujours une mauvaise idée. Ce qu'il fait est de créer de multiples versions de votre code source, qui doivent toutes être testées, ce qui est une douleur, de dire le moins. Malheureusement, comme beaucoup de mauvaises choses, il est parfois inévitable. Je l'utilise dans de très petites quantités lorsque vous écrivez le code qui doit être porté entre Windows et Linux, mais si je me suis retrouvé en train de le faire beaucoup, je prendrais des alternatives, telles que deux sous-arbres de développement distincts. P>
Je pense que vous êtes trop général ici. La compilation conditionnelle n'est pas toujours une mauvaise idée, mais plusieurs des cas d'utilisation courants sont.
Je ne peux pas être d'accord. C'est comme dire "les pointeurs sont mauvais parce que tu peux être vissé". La compilation conditionnelle peut être utilisée à droite puis il ne fait pas trop mal.
"Créez plusieurs versions ..." Ce n'est pas une faute de la compilation conditionnelle, si vous besoin B> pour créer différentes versions du code (comme le code multi-plate-forme), alors que vous l'écrivez, vous aurez besoin de pour tester plusieurs versions.
"Deux arbres de développement distincts" Comment va-t-il mieux que la compilation conditionnelle?
@ybung C'est mieux parce que nous avons des outils (comme VCS, DIFF, etc.) pour gérer plusieurs arbres sources - nous n'avons pas de bons outils pour gérer la compilation conditionnelle.
@unquiet: Vous n'avez pas besoin de gérer la compilation conditionnelle. Avec la compilation conditionnelle, vous écrivez le "diff" dans la source elle-même. Si vous passez à plusieurs arbres de développement alors b> Votre maintenance devient mal à la tête et alors b> vous avez besoin de VCS et d'autres outils pour gérer votre code source en double.
Plusieurs arbres sources sont une mauvaise idée. Si vous trouvez un bogue dans un endroit, vous devrez modifier plusieurs fichiers pour effectuer le correctif sur toutes les plateformes. Gardez le code localisé de manière à ce qu'il puisse être maintenu à un seul point.
Fondamentalement, vous devriez essayer de conserver la quantité de code conditionnellement compilé au minimum, car vous devriez essayer de tester tout cela et que de nombreuses conditions rendent cela plus difficile. Il réduit également la lisibilité du code; La compilation conditionnelle des fichiers entiers est plus claire, par exemple, en mettant le code spécifique à la plate-forme dans un fichier séparé pour chaque plate-forme et que tous ont toutes les mêmes API du point de vue du reste du problème. Essayez également d'éviter de l'utiliser dans des en-têtes de fonction; Encore une fois, c'est parce que c'est un endroit où il est particulièrement déroutant. P>
Mais cela ne veut pas dire que vous ne devriez jamais utiliser la compilation conditionnelle. Essayez simplement de le garder court et minimal. (Où je peux, j'utilise la compilation conditionnelle pour contrôler les définitions d'autres macros qui sont ensuite utilisées dans le reste du code; cela semble être plus clair pour moi au moins.) P>
Les bonnes idées: p>
extern "c" { code> et } code> de sorte que les mêmes en-têtes puissent être utilisés par la mise en œuvre C ++ et par les clients C de l'API LI >
ul>
la mauvaise idée: p>
- Changer l'API entre les drapeaux compilés, car cela oblige le client à modifier ses utilisations avec les mêmes drapeaux de compilation ... URK! LI>
ul>
Je ne sais pas si le deuxième point de votre section "bonnes idées" est vraiment valable, étant donné des bibliothèques portables telles que Boost / Apr, etc. Je devrais imaginer qu'il existe très peu de cas d'angle où il y a quelque chose de plate-forme spécifique à être manipulé dans un tel bloc. Je pense que dans ce cas particulier, vous ferez mieux de s'appuyer sur les maquillages pour créer des implémentations appropriées pour la plate-forme plutôt que la compilation conditionnelle de blocs dans le même dossier ...
Une plus bonne idée: de compiler conditionnellement extern "c" { code> dans les fichiers d'en-tête destinés à exposer les API C à C ++. La mauvaise idée devrait être "tout le reste".
@Nim: Je suis d'accord, je suis le projet de Clang pour le moment, qui comprend le Libc ++ de Howard Hinnant, donc je suis dans un état d'esprit assez bas de bas niveau :) @jeremyP: mentionné merci, comme pour "tout le reste", bien que cela soit tentant, Je préfère éviter les généralisations balayantes.
NIM: Boost est tout simplement trop gras pour voler, mais même l'introduction de APR comme une dépendance peut souvent être déraisonnable lorsque tout ce que vous aviez vraiment besoin était un couple d'IFDEF. D'autre part, les IFDEFS sont tout simplement mauvais si vous ne finissez jamais le code dans l'un des conditionnels. Mais ce n'est pas unique à IFDEFS de Code conditionnel normal.
@ Kusma, le problème est que le "couple d'IFDEFS" ne reste pas nécessairement un couple si c'est vraiment?
@Nim: En fait, cela fait souvent si vous maintenez votre code de manière saine.
C'est une mauvaise idée chaque fois que vous ne savez pas ce que vous faites. Cela peut être une bonne idée lorsque vous résolvez efficacement un problème de cette façon :). P>
La façon dont vous décrivez la compilation conditionnelle, inclure les gardes en font partie. Ce n'est pas seulement une bonne idée de l'utiliser. C'est un moyen d'éviter les erreurs de compilation. P>
Pour moi, la compilation conditionnelle est également un moyen de cibler plusieurs compilateurs et systèmes d'exploitation. Je suis impliqué dans une libère qui est censée être compilable sur Windows XP et plus récente, 32 ou 64 bits, à l'aide de Mingw et Visual C ++, sur Linux 32 et 64 bits à l'aide de GCC / G ++ et sur MacOS utilisant I-Ne -rez-le-savez -Quelle (je ne maintient pas cela, mais je suppose que c'est un port de GCC). Sans les conditions de préprocesseur, il serait très impossible de créer un seul fichier source compilable n'importe où. P>
Dans le passé si vous vouliez produire un code véritablement portable, vous devez recourir à une forme de compilation conditionnelle. Avec une prolifération de bibliothèques portables (telles que APR, Boost, etc.) Cette raison a peu de poids impho. Si vous utilisez une compilation conditionnelle, compilez simplement des blocs de code qui n'ont pas besoin de constructions particulières, vous devriez vraiment revoir votre conception - je devrais imaginer que cela deviendrait un cauchemar à maintenir. P>
Après avoir dit tout cela, si vous avez besoin d'utiliser la compilation conditionnelle, je me cacherais autant que possible du corps principal du code et de limiter à des cas très spécifiques qui sont très bien compris. P>
Les utilisations bonnes / justifiables sont basées sur l'analyse des coûts / avantages. Évidemment, les gens ici sont très conscients des risques: p>
Mais, il y a des utilisations qui tombent souvent dans la catégorie nette-avantages: p>
principal () code> pour une application autonome par rapport à une bibliothèque li>
- Contrôle du code Inclusion pour des modes de construction logiques distincts tels que le débogage et la libération li>
ul>
Une autre utilisation pragmatique de compile conditionnelle consiste à "commenter" des sections de code contenant des commentaires "C" standard (I.E. / * * /). Certains compilateurs n'autorisent pas la nidification de ces commentaires, par exemple: (comme vous pouvez le constater dans la sélection de la syntaxe, Stackoverflow ne nid pas les commentaires.) P> Peut utiliser #Ifdef code> pour obtenir le bon effet, par exemple: p>
Pourquoi ne pas utiliser le plus simple #if 0 code>?
__ NOT_DEFINÉ __ CODE> est réservé à la mise en œuvre (selon les spécifications de la langue) car il contient des doubles traits de soulignement.
Bon point. Éditera l'article original pour contenir un soulignement de premier plan.
Ne mettez pas IFDEF dans votre code.
Cela rend vraiment difficile de lire et de comprendre. Veuillez rendre le code aussi facile à lire que possible pour le responsable (il sait où vous vivez et possède une hache).
masque le code conditionnel dans des fonctions séparées et utilisez l'IFDEF pour définir les fonctions utilisées. P >
ne forts> utilise la partie d'autre pour faire une définition. Si vous dingez que vous dites, une plate-forme est unique et que tous les autres sont les mêmes. Ceci est peu probable, ce qui est probablement que vous savez que vous savez ce qui se passe sur quelques plates-formes, mais vous devez utiliser la section #elle pour coller un #Error, donc lorsqu'il est porté à une nouvelle plate-forme, un développeur doit résoudre explicitement la condition de Sa plate-forme. p> ne doit pas être tenté d'étendre une macro dans plusieurs lignes de code. Cela mène à la folie. P> Si vous développez le code sur Windows, testez sur Solaris 3_1_1 plus tard, vous pouvez trouver des bugs inattendus lorsque les gens font des bugs comme: p> xh h3>
pH h3>
x.h: juste pour l'exactitude: API Mentionné: Unix sait sommeil (secondes), gagnez le sommeil (MS) (je suis sûr que Loki sait, juste un bout de stylo ...)
P.H: Je veux juste annoter: être plus précis: avoir plusieurs déclarations dans la même macro (tout garder sur une seule ligne ne change rien); D'autre part: on peut faire de telles choses, si on leur fait raison (e. g. en enveloppant les déclarations dans une instruction DO {/*...*/} (FALSE)). Quoi qu'il en soit, je ne veux pas propager cela, d'autres moyens (comme l'allusion de la fonction) sont plus appropriés dans la plupart des cas.
Cette question est trop non spécifique et à mon avis n'a pas de réponse définitive. Pouvez-vous fournir un scénario spécifique dans lequel vous envisagez d'utiliser une compilation conditionnelle?
J'ai vu certains cas où je pense que cela a été fait plutôt mal (à mon avis) et je pensais que ce serait une bonne idée de jeter ceci à la communauté. Je suis sûr que nous pouvons trouver de bonnes lignes directrices.
@ Space_C0WB0Y Je pense que cela pourrait être mériter le wiki communautaire peut-être, plutôt que nécessairement être «non spécifique». Il existe des instances spécifiques où le préprocesseur est vraiment une bonne idée et d'autres où ce n'est pas le cas.
Êtes-vous court-circuiter ou quelque chose?