Экранирование символа # в макросе #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
макросы без параметров, но я не тестировал макросы с параметрами).
#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);