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

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

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

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

И используйте это так:

MACRO(Test)

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

#include "Testfoo"

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

'#' is not followed by a macro parameter

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

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

8 ответов

Решение

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

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

#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 HASH_SIGN #
BOOST_PP_CAT(HASH_SIGN, include)

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

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

int Param;
printf("%s = %i\n", GETNAME(PARAM_NAME), PARAM_NAME);
Другие вопросы по тегам