Переменные аргументы
Переменные функции — это функции, которые могут вызываться с разным количеством аргументов.
Только прототипированные объявления функций могут быть переменными. Это обозначается параметром в форме ..., который должен быть последним в списке параметров и должен следовать за хотя бы одним именованным параметром(до C23). Параметр с многоточием и предшествующий параметр должны быть разделены ,.
// Prototyped declaration
int printx(const char* fmt, ...); // function declared this way
printx("hello world"); // may be called with one
printx("a=%d b=%d", a, b); // or more arguments
int printz(...); // OK since C23 and in C++
// Error until C23: ... must follow at least one named parameter
// int printy(..., const char* fmt); // Error: ... must be the last
// int printa(const char* fmt...); // Error in C: ',' is required; OK in C++При вызове функции каждый аргумент, являющийся частью списка переменных аргументов, подвергается специальным неявным преобразованиям, известным как стандартные продвижения аргументов.
Внутри тела функции, использующей переменные аргументы, значения этих аргументов могут быть доступны с помощью <stdarg.h> средств библиотеки:
Определено в заголовке <stdarg.h> |
|
|---|---|
| разрешает доступ к аргументам переменных функций (макрос функции) |
|
| получает следующий аргумент переменной функции (макрос функции) |
|
|
(C99) | создаёт копию аргументов переменной функции (макрос функции) |
| завершает проход по аргументам переменной функции (макрос функции) |
|
| хранит информацию, необходимую для va_start, va_arg, va_end и va_copy (typedef) |
|
Примечания
Хотя старые стили (без прототипов) объявлений функций позволяют последующим вызовам функций использовать любое количество аргументов, они не могут быть переменными (начиная с C89). Определение такой функции должно указывать фиксированное количество параметров и не может использовать stdarg.h макросы.
// old-style declaration, removed in C23
int printx(); // function declared this way
printx("hello world"); // may be called with one
printx("a=%d b=%d", a, b); // or more arguments
// the behavior of at least one of these calls is undefined, depending on
// the number of parameters the function is defined to takeПример
#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++ по Переменным аргументам |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/variadic