6.21 Макросы с переменным числом аргументов.
В стандарте ISO C 1999 года макрос может быть объявлен для приема переменного числа аргументов, так же как и функция. Синтаксис определения макроса аналогичен синтаксису функции. Вот пример:
#define debug(format, ...) fprintf (stderr, format, __VA_ARGS__)
Здесь ‘…’ — переменные аргументы. При вызове такого макроса он представляет собой ноль или более токенов до закрывающей скобки, завершающей вызов, включая любые запятые. Этот набор токенов заменяет идентификатор __VA_ARGS__ в теле макроса повсюду, где он встречается. Более подробную информацию см. в руководстве по CPP.
GCC давно поддерживает макросы с переменным числом аргументов и использует другой синтаксис, который позволяет присваивать имя переменным аргументам, как и любому другому аргументу. Вот пример:
#define debug(format, args...) fprintf (stderr, format, args)
Это во всех отношениях эквивалентно приведенному выше примеру ISO C, но, возможно, более читаемо и наглядно.
GNU CPP имеет два дополнительных расширения макросов с переменным числом аргументов и позволяет использовать их с любым из вышеперечисленных способов определения макроса.
В стандартном C вам не разрешается опустить переменный аргумент полностью; но вам разрешается передать пустой аргумент. Например, этот вызов недействителен в ISO C, потому что после строки нет запятой:
debug ("A message")
GNU CPP позволяет полностью опустить переменные аргументы таким образом. В приведенных выше примерах компилятор будет жаловаться, хотя поскольку расширение макроса все еще содержит дополнительную запятую после строки форматирования.
Для решения этой проблемы CPP ведет себя особым образом для переменных аргументов, используемых с оператором склеивания токенов ‘##’. Если вместо этого вы напишите
#define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
и если переменные аргументы опущены или пусты, оператор ‘##’ заставляет препроцессор удалить запятую перед ним. Если вы предоставите некоторые переменные аргументы в своем вызове макроса, GNU CPP не будет жаловаться на операцию склеивания, а вместо этого поместит переменные аргументы после запятой. Как и любой другой аргумент склеенного макроса, эти аргументы не будут подвергаться макроподстановке.
Далее: Экранированные символы новой строки, Предыдущий: Переменная длина, Вверх: Расширения C [Оглавление][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-9.5.0/gcc/Variadic-Macros.html