Spec-Zone.ru › GCC 5 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);, и сходство WARN_IF с функцией заставило бы программистов C этого захотеть; см. Swallowing the Semicolon.

Строка-представление в C включает больше, чем просто размещение двойных кавычек вокруг фрагмента. Препроцессор экранирует обратной косой чертой кавычки, окружающие вложенные строковые константы, и все обратные косые черты внутри строковых и символьных констант, чтобы получить действительную строковую константу 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 раскрывается (см. Argument Prescan). Следовательно, к тому времени, когда str получает свой аргумент, он уже раскрыт макросом.

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

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

Spec-Zone.ru

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