Стрификация - как это работает?

Я знаю это:

#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",

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

2 ответа

Решение

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

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

Таким образом, с 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(<foo-value>)т.е. 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) с <foo-value> + 1т.е. 4 + 1
  2. Нечего больше заменить. Отделка.

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

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

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

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

Другие вопросы по тегам