Варіати́вний ма́крос — можливість препроцесором Сі за допомогою спеціального макроса оголошувати підтримку різного числа аргументів.
Макрос зі змінним числом аргументів представлено 1999 року в ревізії ISO/IEC 9899:1999 (C99) стандарту мови програмування C. Також такі макроси 2011 року введено в ревізію ISO/IEC 14882:2011 (C++11) стандарту мови програмування C++Working draft changes for C99 preprocessor synchronization — http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1653.htm .
Синтаксис оголошення Синтаксис оголошення схожий зі синтаксисом варіативної функції: пропуск «...» використовується для позначення того, що можна передати нуль або більше аргументів. При розширенні макросом, кожен виклик спеціального ідентифікатора __VA_ARGS__ у списку заміщення макроса замінюється переданими аргументами.
Доступ до індивідуальних аргументів у списку формальних параметрів не здійснюється ні за значенням, ні за способом, яким їх передано.
У gcc у списку формальних параметрів макроса можуть бути як позначені аргументи (), так і передані варіативно (див. приклад).
Підтримка GNU Compiler Collection, починаючи з версії 3.0, C++ Builder 2006 і Visual Studio 2005 підтримують макроси зі змінним числом аргументів при компіляції коду як мовою C, так і мовою C++. Крім того, GCC підтримує варіативні макроси при компіляції коду мовою Objective-C.
Приклад Якщо потрібно printf-подібній функції dprintf(), що приймає ім'я файлу і номер рядка, з якого викликається як аргумент, можна використати такий макрос:void realdprintf (char const *file, int line, char const *fmt, ...); #define dprintf(...) realdprintf(__FILE__, __LINE__, __VA_ARGS__)dprintf() можна викликати як:dprintf("Hello, world");який доповнюється до:realdprintf(__FILE__, __LINE__, "Hello, world"); або:dprintf("%d + %d =%d", 2, 2, 5);який доповнюється до: realdprintf(__FILE__, __LINE__, "%d + %d =%d", 2, 2, 5);
Альтернативи У деяких випадках альтернативою варіативним макросам може стати звичайний макровиклик. Наприклад, такий код можна використати для налагодження:#ifdef TRACING #define TRACE(_p) printf _p #else #define TRACE(_p) #endifЯкщо макрос TRACING визначено під час компіляції, виклик макроса TRACE буде еквівалентним виклику функції printf:TRACE(("Виконується рядок %d\n", __LINE__));Якщо макрос TRACING не визначено, під час роботи програми повідомлення не друкуватиметься. Зверніть увагу, що параметри виклику цього макроса слід укласти в подвійні дужки.
У деяких інших випадках замість варіативних макросів можна використати функціонал stdargs мов C/C++ і виклик функції vprintf.
Інший приклад:#if defined ( DEBUG_MCU ) #define TRACE( args ... ) printf( args ) #else #define TRACE( args ... ) #endif
Див. також Варіативна функція Варіативний шаблон
Примітки
Джерела 1.5.2. Виклик функції зі змінним числом параметрів