Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Информатика 1.docx
Скачиваний:
11
Добавлен:
26.09.2019
Размер:
364.88 Кб
Скачать

Вызов функции с переменным числом параметров

В языке C возможно создание и применение функций с переменным числом параметров. Типичными примерами таких функций являются функции из библиотеки функций языка C, осуществляющие операции форматированного ввода-вывода (printf, scanf и т.п.).

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

int func(int x,...);

int func(int,...);

Все аргументы, заданные в вызове функции, размещаются в стеке – специальной области памяти, используемой для различных операций, в том числе и для передачи аргументов в функции. При этом количество аргументов, помещаемых в стек определяется при вызове функции, например, при вызове func(1,2,3,4); в стек будет помещено 4 аргумента. Ответственность за извлечение правильного количества аргументов полностью лежит на программисте, создающем функцию.

При написании тела функции необходимо извлекать её аргументы из стека. Для обеспечения удобного способа доступа к аргументам функции с переменным числом параметров имеются три макроопределения (макросы) va_start, va_arg, va_end, находящиеся в заголовочном файле stdarg.h.

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

Макрос va_start предназначен для установки аргумента arg_ptr на начало списка необязательных параметров и имеет следующий вид:

void va_start(arg_ptr,prav_param);

Параметр prav_param должен быть последним обязательным параметром вызываемой функции, а указатель arg_prt должен быть объявлен с предопределением в списке переменных типа va_list в виде:

va_list arg_ptr;

Макрос va_start должен быть использован до первого использования макроса va_arg.

Макрокоманда va_arg обеспечивает доступ к текущему параметру вызываемой функции и тоже имеет вид функции с двумя параметрами

type_arg va_arg(arg_ptr,type);

Эта макрокоманда извлекает значение типа type по адресу, заданному указателем arg_ptr, увеличивает значение указателя arg_ptr на длину использованного параметра (длина type) и таким образом параметр arg_ptr будет указывать на следующий параметр вызываемой функции. Макрокоманда va_arg используется столько раз, сколько необходимо для извлечения всех параметров вызываемой функции.

Макрос va_end используется по окончании обработки всех параметров функции и устанавливает указатель списка необязательных параметров на ноль (NULL).

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

#include <stdio.h>

int mean(int iNum,...);

void main()

{ int n;

n=mean(2,3,4);

/* вызов с четырьмя параметрами */

printf("n=%d",n);

n=mean(5,6,7,8,9,-1);

/* вызов с шестью параметрами */

printf("n=%d",n);

return (0);

}

int mean(int iNum,...)

{

int i, sum=0;

va_list uk_arg;

va_start(uk_arg,iNum); // установка указателя uk_arg на

// первый необязательный параметр

for(i=0;i<iNum;i++)

{

sum+=va_arg(uk_arg,int); // Вынимаем очередной параметр

// и прибавляем его к сумме.

}

va_end(uk_arg); // Закрытие списка параметров

return (sum/iNum); // Возвращаем среднее значение

}

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

  1. Функция main. Параметры функции main. Чтение аргументов командной строки.