Задержка расширения макроса - PullRequest
1 голос
/ 13 июля 2011

Рассмотрим этот код:

#define N_ 0
#define N_X 1
#define M(a) N_

M(arg)X;    //  #1 -- I'd like this to expand to N_X, and ultimately 1; but it's 0X instead
M(arg);     //  #2 -- this should and does expand to 0

Проблема с # 1 состоит в том, что после расширения M () результат содержит N_, и перед тем, как объединит его с X, препроцессор найдет и развернет его. Можно ли как-то отложить повторное сканирование результата для дальнейших макросов, чтобы препроцессор нашел N_X вместо N_?

Ответы [ 2 ]

8 голосов
/ 10 мая 2012

Сначала есть различия между N_ X и N_X.Первые два жетона.Чтобы сформировать один токен, вы должны использовать оператор вставки токена ##, но этот оператор запрещает расширение макроса, поэтому:

M(a) ## X //Compiler error can't paste ')' and X

Вызывает ошибку компиляции, потому что он пытается вставить M(a), а неN_.Вы можете разрешить расширение макросов перед вставкой, используя дополнительный уровень макросов (это действительно часто используемый макрос):

#define PRIMITIVE_CAT(x, y) x ## y
#define CAT(x, y) PRIMITIVE_CAT(x, y)

Однако в вашем случае это все равно не будет работать:

 CAT(M(a), X) //expands to 0

Это потому, что вы используете объектные макросы, а не функциональные макросы.Если вы измените его на функциональные макросы, он будет работать так, как вы хотите:

#define N_() 0
#define N_X() 1
#define M(a) N_

CAT(M(arg), X)() // expands to 1
M(arg)()     //  expands to 0

Функциональные макросы более мощные, и вы можете отложить их расширение.Вот как вы можете отложить их для одного сканирования:

#define EMPTY()
#define DEFER(x) x EMPTY()

N_() //Expands to 0
DEFER(N_)() //Expands N_ ()

Задержка раскрытия макроса, как это, является одним из способов реализации рекурсии в препроцессоре.

1 голос
/ 13 июля 2011

Нет.Препроцессор работает построчно и не выполняет никакой рекурсии или возврата.Он читает строку, обрабатывает специальную строку # или подставляет что-либо и переходит на следующую строку.Это также означает, что он не делает никаких замен до #define или после #undef.Вам придется обойти эту проблему.

...