Какой точный шаг расширения макроса? - PullRequest
8 голосов
/ 19 июля 2011

Это не работает, как ожидалось:

#define stringify(x) #x  
printf("Error at line " stringify(__LINE__));

Это работает:

#define stringify1(x) #x  
#define stringify(x) stringify1(x)  
printf("Error at line " stringify(__LINE__));  

Какой приоритет использует препроцесс для расширения таких макросов?

1 Ответ

15 голосов
/ 19 июля 2011

При развертывании макроса препроцессор раскрывает аргументы макроса , только если эти аргументы не подвергаются операторам stringizing (#) или вставки токенов (##) . Итак, если у вас есть это:

#define stringify(x) #x
stringify(__LINE__)

Затем препроцессор не раскрывает __LINE__, потому что это аргумент оператора stringizing. Однако, когда вы делаете это:

#define stringify1(x) #x
#define stringify(x) stringify1(x)
stringify(__LINE__)

Затем при расширении stringify препроцессор расширяет __LINE__ до текущего номера строки, поскольку x не используется ни с операторами строкового преобразования, ни с вставкой токена в определении stringify. Затем он расширяется stringify1, и мы получаем то, что хотели.

Соответствующий язык из стандарта C99 взят из §6.10.3.1 / 1:

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

Пункты § 6.10.3.2 и 6.10.3.3 продолжают определять поведение операторов # и ## соответственно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...