web-dev-qa-db-fra.com

Échapper à un symbole # dans une macro #define?

Sans entrer dans les détails sanglants, je veux utiliser un #define macro qui se développera en #include mais le signe '#' déroute le préprocesseur (car il pense que je veux citer un argument.)

Par exemple, je veux faire quelque chose comme ceci:

#define MACRO(name) #include "name##foo"

Et utilisez-le ainsi:

MACRO(Test)

Qui s'étendra à:

#include "Testfoo"

Le signe humble # fait éclater le préprocesseur. MinGW me donne l'erreur suivante:

'#' is not followed by a macro parameter

Je suppose que je dois échapper au signe # mais je ne le fais pas si c'est même possible.

Oui, les macros sont vraiment mauvaises ...

39
Rob

Pour autant que je me souvienne, vous ne pouvez pas utiliser une autre directive de préprocesseur dans define.

30
EFraim

Il est possible d'insérer un jeton de hachage dans le flux de jetons prétraité. Vous pouvez le faire comme suit:

#define MACRO(hash, name) hash include name
MACRO(#,"hello")

—S'élargit à:

# include "hello"

Cependant, la norme exclut explicitement toute autre analyse d'une telle ligne pour l'existence de directives de prétraitement [cpp.rescan]:

La séquence de jetons de prétraitement complètement remplacée par macro résultante n'est pas traitée comme une directive de prétraitement même si elle en ressemble à une.

34
ybungalobill

Le problème n'est pas réellement d'obtenir un symbole # dans la sortie de votre préprocesseur.

Apparemment, vous voulez que le préprocesseur analyse à nouveau votre fichier, pour gérer les nouvelles directives #include dans le cadre de l'expansion des macros. Cela ne fonctionne pas de cette façon. Si une ligne commence par #, c'est une instruction pour le préprocesseur et interprétée. Si une ligne ne commence pas par #, elle est uniquement soumise à la transformation du préprocesseur, y compris la substitution de macro. Il s'agit d'un test une fois par ligne.

MACRO(Test)

ne commence pas par #. Par conséquent, il n'est pas interprété comme une directive de préprocesseur; au lieu de cela, il est soumis aux règles de remplacement des macros.

28
MSalters

En effet, le # a une signification particulière lorsqu'il est utilisé dans une macro.

#  means quote the following token (which should be a macro parameter name)
## means concatenate the preceding and following tokens.

Dans votre situation, le # n'est pas suivi d'un jeton approprié. Donc, dans votre situation, nous devons passer par un niveau d'indirection:

#define     QUOTE(name)     #name
#define     TEST(name)      QUOTE(name ## foo)

#include TEST(scot)
11
Martin York

Tu ne peux pas faire ça. Les directives du préprocesseur sont reconnues avant l'expansion des macros; si la macro se développe en quelque chose qui ressemble à une directive de préprocesseur, cette directive ne sera pas reconnue. Le mieux que vous puissiez faire est de créer une macro pour le nom de fichier:

#define MACRO(name) "name##foo"
...
#include MACRO(Test)
6
John Bode

Cela pourrait fonctionner (cela fonctionne pour les #define macros sans paramètres, mais je ne l'ai pas testé avec des macros avec paramètres).

#define MACRO(name) <name##foo>
#include MACRO(Test)
2
Sam Harwell
#define PARAM_NAME Param
#define GETNAME_(a) #a
#define GETNAME(a) GETNAME_(a)

int Param;
printf("%s = %i\n", GETNAME(PARAM_NAME), PARAM_NAME);
1
user6858363
#define HASH_SIGN #
BOOST_PP_CAT(HASH_SIGN, include)
1
David F.