Variadic arguments
Вариативные функции - это функции, которые могут вызываться с разным количеством аргументов.
Только прототипированные объявления функций могут быть вариативными. Это обозначается параметром вида ... , который должен находиться последним в списке параметров и должен следовать после как минимум одного именованного параметра (до 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
|