Spec-Zone.ru › GCC 11 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-11.4.0/cpp/Traditional-macros.html

Spec-Zone.ru

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