Spec-Zone.ru › GCC 8 CPP

3.4 Строкизация

Иногда вам может потребоваться преобразовать аргумент макроса в строковую константу. Параметры не заменяются внутри строковых констант, но вместо этого можно использовать препроцессорный оператор ‘#’. Когда параметр макроса используется с ведущим ‘#’, препроцессор заменяет его фактическим текстом аргумента, преобразованным в строковую константу. В отличие от обычной замены параметра, аргумент сначала не расширяется как макрос. Это называется строкизацией.

Нет способа объединить аргумент с окружающим текстом и строкизировать всё вместе. Вместо этого можно написать ряд смежных строковых констант и строкизированных аргументов. Препроцессор заменяет строкизированные аргументы строковыми константами. Затем компилятор C объединяет все смежные строковые константы в одну длинную строку.

Вот пример определения макроса, использующего строкизацию:

#define WARN_IF(EXP) \
do { if (EXP) \
        fprintf (stderr, "Warning: " #EXP "\n"); } \
while (0)
WARN_IF (x == 0);
     → do { if (x == 0)
           fprintf (stderr, "Warning: " "x == 0" "\n"); } while (0);

Аргумент для EXP заменяется один раз, как есть, в операторе if, и ещё один раз, строкизированный, в аргумент fprintf. Если x был макросом, он бы расширился в операторе if, но не в строке.

do и while (0) — это уловка, позволяющая написать WARN_IF (arg);, что программисты C хотели бы сделать из-за сходства WARN_IF с функцией; см. Проглатывание точки с запятой.

Строкизация в C включает больше, чем просто добавление двойных кавычек вокруг фрагмента. Препроцессор экранирует (backslash-escapes) кавычки, окружающие вложенные строковые константы, и все обратные слэши внутри строковых и символьных констант, чтобы получить корректную строковую константу C с правильным содержимым. Таким образом, строкизация p = "foo\n"; приводит к "p = \"foo\\n\";". Однако обратные слэши, которые не находятся внутри строковых или символьных констант, не дублируются: ‘\n’ само по себе строкизируется как "\n".

Все начальные и конечные пробелы в тексте, подлежащем строкизации, игнорируются. Любая последовательность пробелов посредине текста преобразуется в один пробел в строкизированном результате. Комментарии заменяются пробелами задолго до строкизации, поэтому они никогда не появляются в строкизированном тексте.

Нет способа преобразовать аргумент макроса в символьную константу.

Если вам нужно строкизировать результат расширения аргумента макроса, нужно использовать два уровня макросов.

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

s строкизируется при использовании в str, поэтому он не расширяется как макрос предварительно. Но s — обычный аргумент для xstr, поэтому он полностью расширяется как макрос до того, как сам xstr будет расширен (см. Предварительный просмотр аргумента). Следовательно, к моменту, когда str получает свой аргумент, он уже расширен как макрос.

Далее: Конкатенация, Предыдущее: Аргументы макроса, Наверх: Макросы [Содержание][Индекс]

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-8.5.0/cpp/Stringizing.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API