Экранирование символа # в макросе #define?

не вдаваясь в подробности я хочу использовать #define макрос, который будет расширяться к #include но знак " # " сбивает с толку препроцессор (поскольку он думает, что я хочу процитировать аргумент.)

например, я хочу сделать что-то вроде этого:

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

и используйте его таким образом:

MACRO(Test)

который будет расширяться до:

#include "Testfoo"

скромный знак # вызывает тошноту препроцессора. MinGW дает мне следующее ошибка:

'#' is not followed by a macro parameter

Я думаю, мне нужно избежать знака#, но я этого не делаю, если это вообще возможно.

да, макросы действительно зло...

8 ответов


насколько я помню, вы не можете использовать другую директиву препроцессора в define.


Это is возможно вставить хэш-токен в поток предварительно обработанных токенов. Вы можете сделать это следующим образом:

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

-расширяется:

# include "hello"

, стандарт явно исключает любой дальнейший анализ такой строки для существования директив предварительной обработки [cpp.rescan]:

результирующая полностью замененная макросом последовательность токенов предварительной обработки не обрабатывается как директива предварительной обработки, даже если это напоминает один.


проблема на самом деле не в получении символа # на выходе вашего препроцессора.

по-видимому, вы хотите, чтобы препроцессор повторно обработал ваш файл, чтобы иметь дело с недавно созданными директивами #include как часть расширения макросов. Так не бывает. Если строка начинается с #, это инструкция для препроцессора и толковать. Если строка не начинается с символа #, это только при условии трансформации препроцессора, включая макроподстановка. Это раз-в-линию тест.

MACRO(Test)

не начинается с #. Поэтому он не интерпретируется как директива препроцессора; вместо этого он подчиняется правилам замены макросов.


Это потому, что # имеет особое значение при использовании в макросе.

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

в вашей ситуации за # не следует правильный токен. Поэтому в вашей ситуации нам нужно пройти через уровень косвенности:

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

#include TEST(scot)

вы не можете этого сделать. Директивы препроцессора распознаются перед расширением макроса; если макрос расширяется в нечто, похожее на директиву препроцессора, эта директива не будет распознана. Лучшее, что вы можете сделать, это создать макрос для имени файла:

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

этой может работа (он работает для регулярных #define макросы без параметров, но я не тестировал его с макросами с параметрами).

#define MACRO(name) <name##foo>
#include MACRO(Test)

#define HASH_SIGN #
BOOST_PP_CAT(HASH_SIGN, include)

#define PARAM_NAME Param
#define GETNAME_(a) #a
#define GETNAME(a) GETNAME_(a)

int Param;
printf("%s = %i\n", GETNAME(PARAM_NAME), PARAM_NAME);