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

Spec-Zone.ru

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