Namespaces
Variants

Variadic arguments

From cppreference.net

Вариативные функции - это функции, которые могут вызываться с разным количеством аргументов.

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

// Прототипное объявление
int printx(const char* fmt, ...); // функция объявлена таким образом
printx("hello world");     // может быть вызвана с одним
printx("a=%d b=%d", a, b); // или более аргументами
int printz(...); // OK начиная с C23 и в C++
// Ошибка до C23: ... должен следовать как минимум за одним именованным параметром
// int printy(..., const char* fmt); // Ошибка: ... должен быть последним
// int printa(const char* fmt...);   // Ошибка в C: требуется ','; OK в C++

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

В теле функции, использующей вариативные аргументы, значения этих аргументов могут быть доступны с помощью <stdarg.h> библиотечных средств :

Определено в заголовочном файле <stdarg.h>
обеспечивает доступ к аргументам вариативной функции
(функциональный макрос)
получает следующий аргумент вариативной функции
(функциональный макрос)
(C99)
создает копию аргументов вариативной функции
(функциональный макрос)
завершает обход аргументов вариативной функции
(функциональный макрос)
содержит информацию, необходимую для работы va_start , va_arg , va_end и va_copy
(определение типа)

Содержание

Примечания

Хотя устаревшие (без прототипов) объявления функций позволяют последующим вызовам функций использовать любое количество аргументов, они не могут быть вариативными (начиная с C89). Определение такой функции должно указывать фиксированное количество параметров и не может использовать макросы stdarg.h .

// объявление в старом стиле, удалено в C23
int printx(); // функция, объявленная таким образом
printx("hello world");     // может быть вызвана с одним
printx("a=%d b=%d", a, b); // или более аргументами
// поведение по крайней мере одного из этих вызовов неопределено, в зависимости от
// количества параметров, которые принимает функция

Пример

#include <stdio.h>
#include <time.h>
#include <stdarg.h>
void tlog(const char* fmt,...)
{
    char msg[50];
    strftime(msg, sizeof msg, "%T", localtime(&(time_t){time(NULL)}));
    printf("[%s] ", msg);
    va_list args;
    va_start(args, fmt);
    vprintf(fmt, args);
    va_end(args);
}
int main(void)
{
   tlog("logging %d %d %d...\n", 1, 2, 3);
}

Вывод:

[10:21:38] logging 1 2 3...

Ссылки

  • Стандарт C17 (ISO/IEC 9899:2018):
  • 6.7.6.3/9 Деклараторы функций (включая прототипы) (стр: 96)
  • 7.16 Переменное количество аргументов <stdarg.h> (стр: 197-199)
  • Стандарт C11 (ISO/IEC 9899:2011):
  • 6.7.6.3/9 Деклараторы функций (включая прототипы) (стр. 133)
  • 7.16 Переменное количество аргументов <stdarg.h> (стр. 269-272)
  • Стандарт C99 (ISO/IEC 9899:1999):
  • 6.7.5.3/9 Деклараторы функций (включая прототипы) (стр: 119)
  • 7.15 Переменное количество аргументов <stdarg.h> (стр: 249-252)
  • Стандарт C89/C90 (ISO/IEC 9899:1990):
  • 3.5.4.3/5 Деклараторы функций (включая прототипы)
  • 4.8 ПЕРЕМЕННОЕ ЧИСЛО АРГУМЕНТОВ <stdarg.h>

Смотрите также

C++ documentation для Variadic arguments