Непревзойденная скобка макро странность - PullRequest
4 голосов
/ 02 ноября 2011

Каков правильный результат предварительной обработки следующих 3 строк в соответствии с правилами C99?

#define y(x) x
#define x(a) y(a
x(1) x(2)))

Кстати, cpp под linux выдает сообщение об ошибке, но я не понимаю, почему ответ не просто

1 2

Если предположить, что cpp верен, а я неправ, я был бы очень благодарен за объяснение.

Ответы [ 2 ]

6 голосов
/ 02 ноября 2011

Когда макрос найден, препроцессор собирает аргументы для макроса и затем сканирует каждый аргумент макроса изолированно, чтобы другие макросы раскрылись в аргументе ДО того, как развернется первый макрос:

6.10.3.1 Подстановка аргумента

После того, как аргументы для вызова функционально-подобного макроса были определены, происходит подстановка аргумента.Параметр в списке замены, за исключением случаев, когда перед ним стоит токен предварительной обработки # или ## или после него идет токен предварительной обработки ## (см. Ниже), заменяется соответствующим аргументом после раскрытия всех содержащихся в нем макросов.Перед заменой токены предварительной обработки каждого аргумента полностью заменяются макросами, как если бы они формировали остальную часть файла предварительной обработки;другие токены предварительной обработки недоступны.

Так что в этом конкретном примере он видит x(1) и расширяет его, давая

y(1 x(2)))

Затем он идентифицирует вызов макроса y(1 x(2)), с аргументом 1 x(2) и предварительно сканирует, что для макросов расширяться.В рамках этого он находит x(2), который расширяется до y(2, а затем вызывает ошибку из-за отсутствия ) для макроса y.Обратите внимание, что в этот момент он все еще стремится расширить аргумент первого макроса y, поэтому он смотрит на него изолированно БЕЗ рассмотрения остального входного файла, в отличие от расширения, которое имеет место для 6.10.3.4

Теперь возникает некоторый вопрос относительно того, должна ли это быть на самом деле ошибка, или же препроцессор должен обрабатывать эту последовательность y(2 как вообще не являющуюся макро-вызовом, так как ')' нет.Если он выполнит последнее, то увеличит этот y-вызов до 1 y(2, который затем будет объединен с остальными входными данными ()) и в конечном итоге расширится до 1 2

0 голосов
/ 02 ноября 2011

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

...