Stringification – как это работает?

Я знаю это:

#define foo 4 #define str(s) #s 

с str(foo) выписывает: "foo" , потому что stringify выполняется сначала из расширения текста, но это:

  #define xstr(s) str(s) #define str(s) #s #define foo 4 

с xstr(foo) выписывает: "4" .

Зачем? Каковы шаги, участвующие в этом процессе?

Соответствующие этапы макрорасширения (в C 2011 [n1570] 6.10.3.1 и C ++ 1998 16.3.1):

  1. Имена процессов, которым предшествуют # или ## .
  2. Применить макрос замену к каждому аргументу.
  3. Замените каждый параметр соответствующим результатом вышеупомянутой замены макроса.
  4. Повторно сканировать дополнительные macros.

Таким образом, при xstr(foo) имеем:

  1. Текст замены, str(s) , не содержит # или ## , поэтому ничего не происходит.
  2. Аргумент foo заменяется на 4 , поэтому он используется как xstr(4) .
  3. В заменяющем тексте str(s) параметр s заменяется на 4 , создавая str(4) .
  4. str(4) повторно сканируется. (Полученные шаги производят ”4” .)

Обратите внимание, что проблема с str(foo) заключается в том, что шаг 2, который заменит foo на 4 , появится после шага 1, который изменяет аргумент на строку. На шаге 1 foo по-прежнему foo ; он не был заменен на 4 , поэтому результат ”foo” .

Вот почему используется вспомогательный макрос. Это позволяет нам выполнить шаг 2, а затем использовать другой макрос для выполнения шага 1.

Первый случай

  1. Оцените str(foo) : замените str(foo) на #foo , то есть "foo"

Второй случай

  1. Оцените xstr(foo) : замените xstr(foo) на str() , то есть str(4)
  2. Оцените str(4) : замените str(4) на #4 , то есть "4"

В общем,

препроцессор оценивает макрофункции, расширяющие макропеременные, пока не будет ничего, чтобы оценить :

Если вы определите

 #define xstr(s) str(s) + 1 #define str(s) s + 1 

в следующем коде

 #define foo 4 int main() { std::cout << str(foo) << '\n' << xstr(foo) << '\n' ; } 

он оценивал бы как

Первая строка

  1. Замените str(foo) на + 1 , т.е. 4 + 1
  2. Больше ничего не замените. Отделка.

И результат 4 + 1

Вторая строка

  1. Замените xstr(foo) на str() + 1 , т.е. str(4) + 1
  2. Замените str(4) на <4-value> + 1 , т.е. 4 + 1
  3. Больше ничего не замените.

И результат 4 + 1 + 1

  • Можем ли мы иметь рекурсивные macros?
  • Компилировать, создавать или архивировать проблемы с Xcode 4 (и зависимостями)
  • Как определить платформу / компилятор из макросов препроцессора?
  • Пространства имен в C
  • Сначала препроцессор C комментирует или расширяет macros?
  • Препроцессор дампа GCC определяет
  • Предупреждение компилятора "No newline at end of file"
  • Тип переменных #define
  • Макросы препроцессора с несколькими линиями
  • Почему #ifndef и #define используются в файлах заголовков C ++?
  • #pragma pack effect
  • Interesting Posts

    Сохранение параметров строки запроса запроса GET в форме JSF

    Параллельный просмотр стороны частичного просмотра диалогового windows Jquery при нажатии кнопки «Сохранить»

    Как получить ответ JSON в Голанге

    ASP.NET Есть ли лучший способ найти элементы управления, которые находятся в пределах других элементов управления?

    R Построение доверительных диапазонов с помощью ggplot

    Недопустимый URI: формат URI не может быть определен

    Как заставить WebKit перерисовывать / перерисовывать для распространения изменений стиля?

    Android-эмулятор спама logcat с «Service com.android.exchange.ExchangeService просочился ServiceConnection …, который был первоначально связан здесь

    Итерационный multidimensional array с вложенным заявлением Foreach

    Как я могу запустить hostnetwork в Windows 8

    Автозагрузка Rails 3

    Как добавить текст в существующий файл в Java

    Сценарий запуска Linux для подключения к bluetooth и cron, чтобы поддерживать связь

    Альтернатива устаревшему setup_environ () для одноразовых скриптов django?

    Чтение цитат / экранированных аргументов правильно из строки

    Давайте будем гением компьютера.