Содержание | Глава 18

Функция va_arg, va_start, va_end, va_copy

#include <stdarg.h>
type va_arg(va_list argptr, type);
void va_copy(va_list target, va_list source);
void va_end(va_list argptr);
void va_start(va_list argptr, last_parm);

Макрос va_copy() добавлен в версии С99.

Для передачи функции переменного числа аргументов совместно используются макросы va_arg, va_start и va_end. Самым распространенным примером функции, которая принимает переменное число аргументов, является функция printf(). Тип va_list определен в заголовке <stdarg.h>.

Общая процедура создания функции, которая может принимать переменное количество аргументов, такова:

Функция должна иметь по крайней мере один известный параметр (может и больше), указываемый до переменного списка параметров. (Такие параметры называются также обязательными, а параметры, следующие за ними — необязательными.) Крайний правый известный параметр называется last_parm. (Он предшествует первому необязательному параметру.) Его имя используется в качестве второго параметра в обращении к макросу va_start(). Чтобы получить доступ к любому дополнительному параметру, сначала необходимо инициализировать указатель-аргумент argptr[1], обратившись к макросу va_start(). (Иными словами, необходимо выполнить вызов va_start(argptr, <имя last_parm>).) После этого значения параметров возвращаются в результате вызова макроса va_arg(). В качестве второго аргумента этого макроса (соответствующего параметру type), нужно указать тип следующего параметра[2]. Наконец, после прочтения всех параметров до возвращения из функции необходимо вызвать макрос va_end(), чтобы гарантировать корректное восстановление стека. Если макрос va_end() вызван не будет, высока вероятность аварийного отказа программы.

Макрос va_copy() копирует список аргументов, обозначенный параметром target, в объект, обозначенный параметром source.

Пример

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

1   1   1   1          1
- + - + - + -- + ... + --
2   4   8   16         2N

Будет выведено

0.968750
#include <stdio.h>
#include <stdarg.h>

double sum_series(int num, ...);

/* Пример переменного числа аргументов - сумма последовательности. */
int main(void)
{
  double d;

  d = sum_series(5, 0.5, 0.25, 0.125, 0.0625, 0.03125);

  printf("Сумма последовательности %f.\n", d);

  return 0;
}

double sum_series(int num, ...)
{
  double sum=0.0, t;
  va_list argptr;

  /* Инициализация argptr */
  va_start(argptr, num);

  /* сумма последовательности */
  for( ; num; num--) {
    t = va_arg(argptr, double); /* получить следующий аргумент */
    sum += t;
  }

  /* выполнение корректного выхода */
  va_end(argptr);
  return sum;
}

Зависимые функции

vprintf()

----------

[1]Он должен быть объявлен, например, так:

va_list argptr;

[2]Ну где вы видели функцию, которой в качестве аргумента передается служебное слово? Конечно, это возможно именно потому, что va_arg() — макрос, а не функция языка С. Кроме того, посмотрите на описание type

va_arg(va_list argptr, type);

Какой же компилятор позволит вам так описывать функцию?!


Содержание | Глава 18