Экранирование символа # в макросе #define?
не вдаваясь в подробности я хочу использовать #define
макрос, который будет расширяться к #include
но знак " # " сбивает с толку препроцессор (поскольку он думает, что я хочу процитировать аргумент.)
например, я хочу сделать что-то вроде этого:
#define MACRO(name) #include "name##foo"
и используйте его таким образом:
MACRO(Test)
который будет расширяться до:
#include "Testfoo"
скромный знак # вызывает тошноту препроцессора. MinGW дает мне следующее ошибка:
'#' is not followed by a macro parameter
Я думаю, мне нужно избежать знака#, но я этого не делаю, если это вообще возможно.
да, макросы действительно зло...
8 ответов
Это 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 PARAM_NAME Param
#define GETNAME_(a) #a
#define GETNAME(a) GETNAME_(a)
int Param;
printf("%s = %i\n", GETNAME(PARAM_NAME), PARAM_NAME);