Почему замены аргумента не заменяются во время повторного сканирования?

Рассмотрите следующие макроопределения и вызов:

#define x x[0]
#define y(arg) arg

y(x)

Этот вызов расширяется до x[0] (протестированный на Visual C++ 2010, g ++ 4.1, mcpp 2.7.2, и Волна).

Почему? А именно, почему это не расширяется до x[0][0]?

Во время макро-замены,

Параметр в заменяющем списке... заменяется соответствующим аргументом после того, как все макросы содержали, там были расширены. Прежде чем быть замененным маркеры предварительной обработки каждого аргумента абсолютно макро-замененный (C++ 03 §16.3.1/1).

Оценивая макро-вызов, мы берем следующие шаги:

  • Подобный функции макрос y вызывается с x как аргумент в пользу arg параметр
  • x в аргументе макрозаменяется для становления x[0]
  • arg в замене список заменяется макрозамененным значением аргумента, x[0]

Заменяющий список после замены всех параметров x[0].

После того, как всеми параметрами в заменяющем списке заменили, получающаяся маркерная последовательность предварительной обработки повторно сканируется... для большего количества макро-имен к замене (C++ 03 §16.3.4/1).

Если название заменяемого макроса найдено во время этого сканирования заменяющего списка... это не заменяется. Далее, если какие-либо вложенные замены встречаются с названием заменяемого макроса, это не заменяется (C++ 03 §16.3.4/2).

Заменяющий список x[0] повторно сканируется (обратите внимание, что название заменяемого макроса y):

  • x идентифицируется как подобный объекту макро-вызов
  • x заменяется x[0]

Замена останавливает в этой точке из-за правила в §16.3.4/2 предотвращение рекурсии. Заменяющий список после повторного сканирования x[0][0].

Я ясно неправильно истолковал что-то, так как все препроцессоры, которые я протестировал, говорят, что я неправ. Кроме того, этим примером является часть большего примера в C++ 0x FCD (в §16.3.5/5), и это также говорит, что ожидаемая замена x[0].

Почему x не замененный во время повторного сканирования?

C99 и C++ 0x эффективно имеют ту же формулировку как C++ 03 в заключенных в кавычки разделах.

12
задан Brian Tompsett - 汤莱恩 24 February 2016 в 19:51
поделиться

1 ответ

Я считаю, что вы процитировали ключевой абзац, вы просто остановились слишком рано. 16.3.4 / 2 (выделено мной):

Если имя заменяемого макроса найдено во время этого сканирования список замены (не включая остальная часть исходного файла токены предварительной обработки), это не заменены. Далее, если есть вложенные встреча замен имя заменяемого макроса, он не заменяется. Эти незамещенные токены предварительной обработки имени макроса отсутствуют больше доступен для дальнейшего замена , даже если они позже (повторно) изучены в контексте, в котором токен предварительной обработки имени макроса в противном случае были заменены.

Таким образом, когда x заменяется на x [0] во время подстановки параметра y , он полностью заменяется макросом, что означает повторное сканирование в этот момент x перехватывается правилом рекурсии. Это означает, что x в x [0] больше не подлежит дальнейшей замене, в том числе во время повторного сканирования частично развернутого результата y (x) .

17
ответ дан 2 December 2019 в 19:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: