va_arg
, , va_copy
va_end
va_start
Обращается к списку с переменным количеством аргументов.
Синтаксис
type va_arg(
va_list arg_ptr,
type
);
void va_copy(
va_list dest,
va_list src
); // (ISO C99 and later)
void va_end(
va_list arg_ptr
);
void va_start(
va_list arg_ptr,
prev_param
); // (ANSI C89 and later)
void va_start(
arg_ptr
); // (deprecated Pre-ANSI C89 standardization version)
Параметры
type
Тип аргумента, который требуется извлечь.
arg_ptr
Указатель на список аргументов.
dest
Указатель на список аргументов, которые нужно инициализировать из параметра src
src
Указатель на инициализированный список аргументов, которые требуется скопировать в параметр dest
.
prev_param
Параметр, который предшествует первому необязательному аргументу.
Возвращаемое значение
va_arg
возвращает текущий аргумент. va_copy
, va_start
и va_end
не возвращайте значения.
Замечания
Макросы va_arg
, va_copy
, va_end
и va_start
предоставляют переносимый способ получения аргументов функции, которая принимает переменное число аргументов. Существует две версии макросов: макросы, определенные в STDARG.H
соответствии со стандартом ISO C99; макросы, определенные в VARARGS.H
нерекомендуемом виде, но сохраняются для обратной совместимости с кодом, написанным до стандарта ANSI C89.
Эти макросы предполагают, что функции принимают фиксированное число обязательных аргументов, за которыми следует переменное число необязательных аргументов. Обязательные аргументы объявляются как обычные параметры для функции и доступ к ним возможен через имена параметров. К необязательным аргументам обращаются макросы (или VARARGS.H
код, написанный до стандарта ANSI C89), который задает указатель на первый необязательный аргумент в списке аргументов STDARG.H
, извлекает аргументы из списка и сбрасывает указатель при завершении обработки аргументов.
Стандартные макросы C, определенные в STDARG.H
, используются следующим образом:
va_start
задает указательarg_ptr
на первый необязательный аргументу в списке аргументов, который передан функции. Аргументarg_ptr
должен иметь типva_list
. Аргументprev_param
— это имя обязательного параметра, который непосредственно предшествует первому необязательному аргументу в списке аргументов. Если параметрprev_param
объявлен в классе регистрового хранения, поведение макроса не определено.va_start
необходимо использовать до первого использованияva_arg
.va_arg
извлекает значениеtype
из расположения, которое задано параметромarg_ptr
, и увеличивает значение указателяarg_ptr
, чтобы он указывал на следующий аргумент в списке, используя размерtype
для определения места начала следующего аргумента.va_arg
можно использовать в функции любое количество раз, чтобы получить аргументы из списка.va_copy
делает копию списка аргументов в текущем состоянии. Параметрsrc
должен быть уже инициализирован с помощьюva_start
; он может быть обновлен вызовамиva_arg
, но не должен быть сброшен с помощьюva_end
. Следующий аргумент, который извлекаетсяva_arg
изdest
, совпадает со следующий аргументом, который извлекается изsrc
.После получения
va_end
всех аргументов сбрасывает указательNULL
на .va_end
должен вызываться для каждого списка аргументов, который инициализируетсяva_start
илиva_copy
, до выполнения возврата функцией.
Примечание.
Макросы в VARARGS.H использовать не рекомендуется; они сохранены только для обратной совместимости с кодом, который написан до появления стандарта ANSI C89. Во всех остальных случаях используйте макросы из файла STDARGS.H.
При компиляции с помощью /clr
(компиляция среды CLR) программы, использующие эти макросы, могут создавать непредвиденные результаты из-за различий между системами типов среды CLR. Рассмотрим следующую программу:
#include <stdio.h>
#include <stdarg.h>
void testit (int i, ...)
{
va_list argptr;
va_start(argptr, i);
if (i == 0)
{
int n = va_arg(argptr, int);
printf("%d\n", n);
}
else
{
char *s = va_arg(argptr, char*);
printf("%s\n", s);
}
va_end(argptr);
}
int main()
{
testit(0, 0xFFFFFFFF); // 1st problem: 0xffffffff is not an int
testit(1, NULL); // 2nd problem: NULL is not a char*
}
Обратите внимание — функция testit
ожидает, что второй параметр будет int
или char*
. Передаваемые аргументы имеют значение 0xffffffff (unsigned int
, а не int
) и NULL
(фактически int
, а не char*
). Когда программа скомпилирована для неуправляемого кода, она дает следующий результат:
-1
(null)
Требования
Заголовок: <stdio.h>
и <stdarg.h>
Устаревший заголовок: <varargs.h>
Библиотеки
Все версии библиотек времени выполнения языка C.
Пример
// crt_va.c
// Compile with: cl /W3 /Tc crt_va.c
// The program below illustrates passing a variable
// number of arguments using the following macros:
// va_start va_arg va_copy
// va_end va_list
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
double deviation(int first, ...);
int main( void )
{
/* Call with 3 integers (-1 is used as terminator). */
printf("Deviation is: %f\n", deviation(2, 3, 4, -1 ));
/* Call with 4 integers. */
printf("Deviation is: %f\n", deviation(5, 7, 9, 11, -1));
/* Call with just -1 terminator. */
printf("Deviation is: %f\n", deviation(-1));
}
/* Returns the standard deviation of a variable list of integers. */
double deviation(int first, ...)
{
int count = 0, i = first;
double mean = 0.0, sum = 0.0;
va_list marker;
va_list copy;
va_start(marker, first); /* Initialize variable arguments. */
va_copy(copy, marker); /* Copy list for the second pass */
while (i != -1)
{
sum += i;
count++;
i = va_arg(marker, int);
}
va_end(marker); /* Reset variable argument list. */
mean = sum ? (sum / count) : 0.0;
i = first; /* reset to calculate deviation */
sum = 0.0;
while (i != -1)
{
sum += (i - mean)*(i - mean);
i = va_arg(copy, int);
}
va_end(copy); /* Reset copy of argument list. */
return count ? sqrt(sum / count) : 0.0;
}
Deviation is: 0.816497
Deviation is: 2.236068
Deviation is: 0.000000
См. также
Доступ к аргументам
vfprintf
, , _vfprintf_l
vfwprintf
_vfwprintf_l