Spec-Zone.ru › GCC 8 CPP

10.2 Традиционные макросы

Основное отличие традиционных и ISO макросов состоит в том, что первые расширяются до текста, а не до последовательности токенов. CPP удаляет все начальные и конечные горизонтальные пробелы из текста замены макроса перед его сохранением, но сохраняет форму внутренних пробелов.

Одним из последствий является то, что в тексте замены допустимо наличие непарной кавычки (см. Традиционный лексический анализ). Незакрытая строка или символьный литерал продолжаются в текст после вызова макроса. Аналогично, текст в конце расширения макроса может слиться с текстом после вызова макроса, чтобы создать один токен.

Обычно комментарии удаляются из текста замены после расширения макроса, но если опция -CC передаётся в командной строке, комментарии сохраняются. (На самом деле, текущая реализация удаляет комментарии даже перед сохранением текста замены макроса, но она делает это таким образом, что наблюдаемый эффект идентичен даже в случае макроса с параметрами.)

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

CPP заменяет имя нескобочного макроса объектного типа своим текстом замены, а затем повторно анализирует его, чтобы найти другие макросы для замены. В отличие от расширения стандартных макросов, расширение традиционных макросов не предусматривает предотвращение рекурсии. Если макрос объектного типа появляется не в кавычках в своём тексте замены, он будет заменён снова во время повторного анализа и так далее до бесконечности. GCC обнаруживает расширение рекурсивных макросов, выводит сообщение об ошибке и продолжает после вызова нарушающего макроса.

#define PLUS +
#define INC(x) PLUS+x
INC(foo);
     → ++foo;

Макросы с параметрами похожи по форме, но существенно отличаются по поведению от своих аналогов ISO. Их аргументы заключены в скобки, разделены запятыми и могут занимать несколько физических строк. Запятые внутри вложенных скобок не обрабатываются как разделители аргументов. Аналогично, кавычка в аргументе не может быть оставлена незакрытой; последующая запятая или скобка, которая появляется перед закрывающей кавычкой, обрабатываются как любой другой символ. Нет механизма для обработки макросов с переменным числом аргументов.

Эта реализация удаляет все комментарии из аргументов макроса, если не указана опция -C. Форма всех других горизонтальных пробелов в аргументах сохраняется, включая начальные и конечные пробелы. В частности

f( )

обрабатывается как вызов макроса ‘f’ с единственным аргументом, состоящим из одного пробела. Если вы хотите вызвать макрос с параметрами, который не принимает аргументов, не оставляйте пробелы между скобками.

Если аргумент макроса переходит на новую строку, новая строка заменяется пробелом при формировании аргумента. Если предыдущая строка содержала незакрытую кавычку, следующая строка наследует состояние кавычки.

Традиционные препроцессоры заменяют параметры в тексте замены их аргументами независимо от того, находятся ли параметры в кавычках или нет. Это предоставляет способ строкового преобразования аргументов. Например

#define str(x) "x"
str(/* A comment */some text )
     → "some text "

Обратите внимание, что комментарий удаляется, но конечный пробел сохраняется. Вот пример использования комментария для эффекта склейки токенов.

#define suffix(x) foo_/**/x
suffix(bar)
     → foo_bar

Далее: Разное для традиционного режима, Предыдущий: Традиционный лексический анализ, Вверх: Традиционный режим [Содержание][Индекс]

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

Spec-Zone.ru

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