Подтвердить что ты не робот

Почему для этого конкатенационного макроса необходим уровень косвенности?

Я нашел интересное небольшое сообщение в блоге, в котором объясняется, как сгенерировать (полу) уникальные имена в макросе, используя номер строки:

// Do magic! Creates a unique name using the line number
#define LINE_NAME( prefix ) JOIN( prefix, __LINE__ )
#define JOIN( symbol1, symbol2 ) _DO_JOIN( symbol1, symbol2 )
#define _DO_JOIN( symbol1, symbol2 ) symbol1##symbol2

Есть две вещи, которые меня действительно путают:

  • Почему макрос LINE_NAME работает даже после объявления JOIN после него в файле? Я думал, что препроцессор C выполнил линейный проход и, следовательно, для определения макросов нужно было бы определить на основе зависимости, точно так же, как функции C должны быть определены до их использования.
  • Почему для получения правильного результата необходимо использовать макросы JOIN и _DO_JOIN? Наличие такого уровня косвенности в макросах кажется очень странным.

У меня такое чувство, что ответы на оба эти вопроса связаны друг с другом и связаны с тем, как препроцессор C оценивает макросы. (Тем не менее, моя интуиция о том, как работают макросы, по-видимому, сработала, поскольку я даже не думал, что пример действителен.)

4b9b3361

Ответ 1

Почему макрос LINE_NAME работает даже если JOIN объявлен после него в файле?

Макросы не являются функциями, когда вы вызываете их, компилятор их расширяет, а компилятор в точке использования знает обо всех определенных макросах.

Почему для получения правильного результата необходимо использовать макросы JOIN и _DO_JOIN? Наличие такого уровня косвенности в макросах кажется очень странным.

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

В противном случае вывод не prefix1234 будет prefix__LINE__.

полезно читать этот ответ и этот поток.