Spec-Zone.ru › GCC 10 CPP

Далее: Переводы строки в аргументах, Предыдущее: Самоссылочные макросы, Вверх: Ловушки макросов [Содержание][Индекс]

3.10.6 Предварительный анализ аргументов ¶

Аргументы макроса полностью макрорасширяются до их подстановки в тело макроса, за исключением случаев, когда они строятся или склеиваются с другими токенами. После подстановки всё тело макроса, включая подставленные аргументы, снова сканируется на макросы для расширения. В результате аргументы сканируются дважды, чтобы расширить вызовы макросов в них.

В большинстве случаев это не оказывает никакого влияния. Если аргумент содержал вызовы макросов, они расширяются во время первого сканирования. В результате расширения не содержит вызовов макросов, поэтому второе сканирование его не изменяет. Если бы аргумент подставлялся как есть, без предварительного сканирования, единственное оставшееся сканирование обнаружило бы те же вызовы макросов и дало бы те же результаты.

Можно ожидать, что двойное сканирование изменит результаты при использовании самоссылочного макроса в аргументе другого макроса (см. Самоссылочные макросы): самоссылочный макрос был бы расширен один раз в первом сканировании и второй раз во втором сканировании. Однако этого не происходит. Самоссылочные элементы, которые не расширяются в первом сканировании, помечаются так, что они не будут расширяться и во втором сканировании.

Можно задаться вопросом: «Зачем упоминать предварительный анализ, если он не влияет на результат? И почему не пропустить его и не сделать препроцессор быстрее?» Ответ состоит в том, что предварительный анализ влияет на результат в трех особых случаях:

  • Вложенные вызовы макроса.

    Мы говорим, что вложенные вызовы макроса происходят, когда аргумент макроса содержит вызов того же самого макроса. Например, если f — это макрос, ожидающий один аргумент, f (f (1)) — это вложенная пара вызовов f. Желаемое расширение выполняется путём расширения f (1) и подстановки его в определение f. Предварительный анализ приводит к ожидаемому результату. Без предварительного анализа f (1) сам бы был подставлен как аргумент, а внутреннее использование f появилось бы во время основного сканирования как косвенная самоссылка и не было бы расширено.

  • Макросы, которые вызывают другие макросы, которые строят или конкатенируют.

    Если аргумент строится или конкатенируется, предварительный анализ не выполняется. Если нужно расширить макрос, а затем построить или конкатенировать его расширение, это можно сделать, заставив один макрос вызвать другой макрос, который выполняет строку или конкатенацию. Например, если у вас есть

    #define AFTERX(x) X_ ## x
    #define XAFTERX(x) AFTERX(x)
    #define TABLESIZE 1024
    #define BUFSIZE TABLESIZE

    тогда AFTERX(BUFSIZE) расширяется до X_BUFSIZE, а XAFTERX(BUFSIZE) расширяется до X_1024. (Не до X_TABLESIZE. Предварительный анализ всегда выполняет полное расширение.)

  • Макросы, используемые в аргументах, чьи расширения содержат незащищённые запятые.

    Это может привести к тому, что макрос, расширенный во втором сканировании, будет вызван с неправильным количеством аргументов. Вот пример:

    #define foo  a,b
    #define bar(x) lose(x)
    #define lose(x) (1 + (x))

    Мы хотели бы, чтобы bar(foo) превратилось в (1 + (foo)), которое затем превратилось бы в (1 + (a,b)). Вместо этого bar(foo) расширяется до lose(a,b), и вы получите ошибку, потому что lose требует одного аргумента. В этом случае проблему легко решить теми же скобками, которые должны использоваться для предотвращения неправильной вложенности арифметических операций:

    #define foo (a,b)
    or
    #define bar(x) lose((x))

    Дополнительная пара скобок предотвращает интерпретацию запятой в определении foo как разделителя аргументов.

Далее: Переводы строки в аргументах, Предыдущее: Самоссылочные макросы, Вверх: Ловушки макросов [Содержание][Индекс]

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

Spec-Zone.ru

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