Экранирование символа # в макросе #define? - PullRequest
37 голосов
/ 16 июля 2009

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

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

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

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

MACRO(Test)

Который расширится до:

#include "Testfoo"

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

'#' is not followed by a macro parameter

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

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

Ответы [ 8 ]

32 голосов
/ 28 ноября 2011

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

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

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

# include "hello"

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

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

29 голосов
/ 16 июля 2009

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

28 голосов
/ 16 июля 2009

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

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

MACRO(Test)

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

11 голосов
/ 16 июля 2009

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

#  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)
6 голосов
/ 16 июля 2009

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

#define MACRO(name) "name##foo"
...
#include MACRO(Test)
2 голосов
/ 16 июля 2009

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

#define MACRO(name) <name##foo>
#include MACRO(Test)
1 голос
/ 21 сентября 2016
#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 голос
/ 12 января 2013
#define HASH_SIGN #
BOOST_PP_CAT(HASH_SIGN, include)
...