Варіативний макрос

Варіати́вний ма́крос — можливість препроцесором Сі за допомогою спеціального макроса оголошувати підтримку різного числа аргументів.

Макрос зі змінним числом аргументів представлено 1999 року в ревізії ISO/IEC 9899:1999 (C99) стандарту мови програмування C. Також такі макроси 2011 року введено в ревізію ISO/IEC 14882:2011 (C++11) стандарту мови програмування C++[1].

Синтаксис оголошення[ред. | ред. код]

Синтаксис оголошення схожий зі синтаксисом варіативної функції: пропуск «...» використовується для позначення того, що можна передати нуль або більше аргументів. При розширенні макросом, кожен виклик спеціального ідентифікатора __VA_ARGS__ у списку заміщення макроса замінюється переданими аргументами.

Доступ до індивідуальних аргументів у списку формальних параметрів не здійснюється ні за значенням, ні за способом, яким їх передано.

У gcc у списку формальних параметрів макроса можуть бути як позначені аргументи (англ. specified arguments), так і передані варіативно (див. приклад).

Підтримка[ред. | ред. код]

GNU Compiler Collection, починаючи з версії 3.0, C++ Builder 2006 і Visual Studio 2005 [1] [Архівовано 8 квітня 2008 у Wayback Machine.] підтримують макроси зі змінним числом аргументів при компіляції коду як мовою 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. Working draft changes for C99 preprocessor synchronization — http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1653.htm [Архівовано 31 липня 2020 у Wayback Machine.]

Джерела[ред. | ред. код]