Spec-Zone.ru › GCC 12 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

Далее: Разное (Traditional miscellany), Предыдущий: Лексический анализ (Traditional lexical analysis), Вверх: Режим традиционных макросов (Traditional Mode) [Оглавление][Индекс]

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

Spec-Zone.ru

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