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"
.
- Есть ли способ сделать #define внутри другого #define?
- Препроцессор C ++ # определение ключевого слова. Соответствует ли это стандартам?
- Легкий способ использовать переменные типов enums как строку в C?
- «#Include» текстовый файл в программе на языке C как символ
- Для чего нужны macros C?
Зачем? Каковы шаги, участвующие в этом процессе?
- Массив общей длины массива для C?
- Каково возможное использование для параметра #define для if (false) {} else for??
- Разрешены ли пустые определения макросов в C? Как они себя ведут?
- Можно ли использовать препроцессор C, чтобы определить, существует ли файл?
- Просмотр расширенных макросов C
- Являются ли typedef и #define одинаковыми в c?
- Препроцессор C ++ идентичен препроцессору C?
- В чем разница между #define и const?
Соответствующие этапы макрорасширения (в C 2011 [n1570] 6.10.3.1 и C ++ 1998 16.3.1):
- Имена процессов, которым предшествуют
#
или##
. - Применить макрос замену к каждому аргументу.
- Замените каждый параметр соответствующим результатом вышеупомянутой замены макроса.
- Повторно сканировать дополнительные macros.
Таким образом, при xstr(foo)
имеем:
- Текст замены,
str(s)
, не содержит#
или##
, поэтому ничего не происходит. - Аргумент
foo
заменяется на4
, поэтому он используется какxstr(4)
. - В заменяющем тексте
str(s)
параметрs
заменяется на4
, создаваяstr(4)
. -
str(4)
повторно сканируется. (Полученные шаги производят”4”
.)
Обратите внимание, что проблема с str(foo)
заключается в том, что шаг 2, который заменит foo
на 4
, появится после шага 1, который изменяет аргумент на строку. На шаге 1 foo
по-прежнему foo
; он не был заменен на 4
, поэтому результат ”foo”
.
Вот почему используется вспомогательный макрос. Это позволяет нам выполнить шаг 2, а затем использовать другой макрос для выполнения шага 1.
Первый случай
- Оцените
str(foo)
: заменитеstr(foo)
на#foo
, то есть"foo"
Второй случай
- Оцените
xstr(foo)
: заменитеxstr(foo)
наstr(
, то есть) str(4)
- Оцените
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' ; }
он оценивал бы как
Первая строка
- Замените
str(foo)
на
, т.е.+ 1 4 + 1
- Больше ничего не замените. Отделка.
И результат 4 + 1
Вторая строка
- Замените
xstr(foo)
наstr(
, т.е.) + 1 str(4) + 1
- Замените
str(4)
на<4-value> + 1
, т.е.4 + 1
- Больше ничего не замените.
И результат 4 + 1 + 1