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

Spec-Zone.ru

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