8
votes

Expansion macro du préprocesseur à une autre directive de préprocesseur

Au départ, je pensais que j'avais besoin de cela, mais je l'ai finalement évité. Cependant, ma curiosité (et l'appétit de connaissances, hum) me font demander:

peut une macro de préprocesseur, par exemple dans xxx

développer à une autre include, comme dans < / p> xxx

?


5 commentaires

Un jour, vous souhaitez transférer votre code sur un système d'exploitation comme Linux, le cas échéant, le cas échéant (c'est-à-dire que c'est important (c'est-à-dire deux fichiers différents), puis toutes les fautes qui ne sont pas pêchées sur Windows rentreront à la maison. Sinon, si vous êtes une personne Linux, vous voudrez un jour envie d'aller dans l'autre sens, avec des problèmes différents mais aussi horribles.


Je suis d'accord avec la règle toujours minuscule pour les noms de fichiers. J'ai écrit de cette façon parce que je voulais exclure la question de la conversion minuscule (nom de classe -> nom de fichier). Mais cela vaut la peine de mentionner, merci. +1!


Notre règle est que les noms de fichiers correspondent exactement au schéma de dénomination de nos types et nos fonctions. Nous faisons exactement comme le questionneur ici, un nappe-type de type sera défini dans FooType.h. Comme avec n'importe quelle directive "style", choisissez un style et collez-le avec elle. Après avoir dit que nous développions lourdement sur Linux et que cette règle est donc automatiquement appliquée pour nous par le système d'exploitation .... hmmmmm .....


D'accord. C'était une erreur. Je n'aime pas avoir les majuscules dans les noms de fichiers, mais j'aime avoir des majuscules dans les noms de type. Mais j'aurais dû écrire les deux minuscules juste pour la question. @RICHARD CORDEN: Le système de fichiers et le compilateur appliquent la règle peut être temporaire, et tout port à d'autres osseux efface complètement cette sécurité. Au moins, avec une règle de nom de fichier minuscule totalitaire, un comportement et des erreurs risqués sont immédiatement visibles, avant que tout problème ne se produise. Ce que je préfère.


@moala. En pensant à cela un peu plus, il m'a frappé que peu importe ce que vous faites (contenus assortis en minuscule ou mixte), il devra être appliqué par un utilité externe. Il y a toujours la chance que quelqu'un fasse une erreur et que si vous avez un support d'OS (comme dans mon cas), vous devez vérifier cela via un script / outil. Il est plus facile de vérifier tous les minuscules - mais il n'est pas difficile de vérifier que le nom correspond au moins un identifiant dans le fichier. Et vous pouvez même avoir un outil d'analyse statique qui fonctionne pour vous !!! ;) .


3 Réponses :


14
votes

Je crois que cela ne peut pas être fait, c'est parce que le pré-processeur est Pass unique . Donc, il ne peut pas émettre d'autres directives de préprocesseur.

Plus précisément, de la norme C99 (6.10.3.4 paragraphe 3):

3 le résultat complètement Jeton de prétraitement à remplacement macro-remplacé la séquence n'est pas traitée en tant que directive de prétraitement même si elle ressemble à un, ...

Assez intéressant, c'est pourquoi l'opérateur _pragma a été ajouté à C99. Parce que #pragma n'a pas pu être émis par les macros, mais _pragma peut.


5 commentaires

Eh bien, cela peut bien sûr émettre les directives. Ce qu'il ne peut pas faire, c'est les traiter dans le même Pass de préprocesseur.


Depuis le # et ## Les caractères ont des significations particulières dans les macros, je ne vois pas comment vous pourriez réellement émettre une directive ...


En fait, le préprocesseur du GCC semble autoriser "#define x #Ifdef x" où l'espace entre le #Ifdef et le second x est vraiment une nouvelle ligne, ce qui émet un #Ifdef lorsque vous exécutez CPP dessus. Quelqu'un d'autre voudra peut-être vérifier cela, comme je venais d'avoir quelques bières :-)


Oui, il semble qu'il soit possible de créer quelque chose qui "ressemble à" une directive, mais la norme indique spécifiquement (voir mon édition) qu'une telle construction n'est pas traitée comme une directive.


Oui, je ne suggérais pas que l'OP puisse faire ce qu'il semble vouloir.



10
votes

La norme C affirme ceci sur les directives de prétraitement (C99 - 6.10 (2) - Directives de prétraitement):

Une directive de prétraitement consiste en une séquence de jetons de prétraitement commençant par un # jeton de prétraitement qui (au début de la phase de traduction 4) ... p> blockquote>

et (C99 - 6.10 (7)): P>

Les jetons de prétraitement dans une directive de prétraitement ne sont pas soumis à macro expansion sauf indication contraire. P>

Exemple dans: P>

# include pp-tokens new-line


4 commentaires

J'ai examiné cette partie de la norme, mais je ne pense pas que ce soit la section la plus pertinente. L'exemple n'est pas celui qui essaie d'émettre une directive. C'est à la place un exemple de directive qui n'est pas précédé par "WhitSpace" (même si la macro vide résout à Whitespace).


J'accepterais que votre devis de la norme est plus directement pertinente, mais ce n'est pas là quand j'ai répondu. Même si l'exemple ci-dessus n'est pas le même que celui qui a été question, le peu de la directive de prétraitement devant être mis en place au début de la phase 4 désactive également les macros d'exploration dans des directives de prétraitement utiles, même si 6.10.3.4 (3) dit aussi directement. (En d'autres termes, même si je ne pense pas que ma réponse est incorrecte, la vôtre est clairement meilleure réponse).


Désolé, mais je devais choisir une bonne réponse. Un autre +1 sur votre avis perspicace d'être aussi juste que possible, j'espère que vous comprenez.


Pas besoin de vous excuser - la réponse d'Evan est définitivement meilleure. Il n'est pas nécessaire de s'excuser même si cela n'était pas le cas.



1
votes

Toutes les directives de préprocesseur sont interprétées avant le début de la macro expansion, donc non, vous ne pouvez pas avoir de macro développer une directive #include et que cela soit interprété comme tel. Au lieu de cela, il sera interprété comme (erroné) C ++ Code.


1 commentaires

Vous pouvez obtenir cette impression car de nombreuses directives désactivent la macro expansion de leurs arguments, mais ce n'est pas vrai. L'expansion macro se produit simultanément avec une analyse de la directive. Si c'était vrai, #si ne fonctionnerait pas, et #undef n'aurait pas l'effet que les gens attendent.