Va_arg   va_start работа с переменным числом параметров


Содержание

SBP-Program

Функции с переменным числом параметров в Си

Что такое функциия с переменным числом параметров в Си?

Как сделать вызов функции с переменным числом параметров?

Функция с переменным числом параметров в Си

Функции с переменным числом параметров. Количество параметров в заголовках таких функций не определено.

Пример работы с функцией с переменным числом параметров:

Для работы с функциями с переменным числом параметров используют макросы из stdarg.h. Вот эти макросы: va_list, va_start, va_arg, va_end.

В нашем примере первым аргументом функции является количество последующих параметров.

Получаем указатель на список параметров:

Просмотр списка параметров начинаем сразу после аргумента nParamCount:

Получаем очередной параметр, int указывает на размер типа параметра:

Va_arg   va_start работа с переменным числом параметров

void va_start(va_list ap , last );
type va_arg(va_list ap , type );
void va_end(va_list ap );
void va_copy(va_list dest , va_list src );

ОПИСАНИЕ

Вызванная функция должна указать на объект типа va_list , который используется макросами va_start , va_arg и va_end .

va_start

Параметр last является именем последнего параметра перед переменным списком аргументов; например, именем последнего параметра, тип которого известен вызывающей функции.

Так как адрес этого параметра может быть использован в макросе va_start , то он не должен быть объявлен как зарегистрированная переменная, функция или тип массива.

va_arg

Первый вызов макроса va_arg сразу после va_start возвращает аргумент после last . Последующие вызовы будут возвращать величины оставшихся аргументов.

Если нет следующего аргумента или если type несовместим с типом следующего аргумента, то могут возникнуть различные ошибки.

Если ap передается функции, использующей va_arg( ap , type ), то значение ap будет неопределено после возвращения функции.

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

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

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

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

Функция должна иметь по крайней мере один известный параметр (может и больше), указываемый до переменного списка параметров. (Такие параметры называются также обязательными, а параметры, следующие за ними — необязательными.) Крайний правый известный параметр называется 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] Он должен быть объявлен, например, так:

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

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

Электроника для всех

Блог о электронике

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

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

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

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

Примерами функций с переменным числом параметров являются функции из библиотеки функций языка СИ, осуществляющие операции ввода-вывода информации (printf,scanf и т.п.). Подробно эти функции рассмотрены во третьей части книги.

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

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

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

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

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

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

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

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

One thought on “1.5.2. Вызов функции с переменным числом параметров”

хотел сначала использовать printf. но почему-то никак не смог переопределить функции в файле write.c(как написано на разных сайтах). Потом решил написать свою упрощенную функцию для форматного вывода. Файл stdarg к проекту подключил, но ругается вот так :
Error[Pe007]: unrecognized token
на строку va_list ар;

Илон Маск рекомендует:  Что такое код bcscale

Что я могу делать не так?

Добавить комментарий Отменить ответ

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.

va_arg, va_copy, va_end, va_start va_arg, va_copy, va_end, va_start

Обращается к списку с переменным количеством аргументов. Accesses variable-argument lists.

Синтаксис Syntax

Параметры Parameters

type type
Тип аргумента, который требуется извлечь. Type of argument to be retrieved.

arg_ptr arg_ptr
Указатель на список аргументов. Pointer to the list of arguments.

dest dest
Указатель на список аргументов, которые должны быть инициализированы из src Pointer to the list of arguments to be initialized from src

src src
Указатель на инициализированный список аргументов для копирования в dest. Pointer to the initialized list of arguments to copy to dest.


prev_param prev_param
Параметр, который предшествует первому необязательному аргументу. Parameter that precedes the first optional argument.

Возвращаемое значение Return Value

va_arg возвращает текущий аргумент. va_arg returns the current argument. va_copy, va_start и va_end не возвращают значения. va_copy, va_start and va_end do not return values.

Примечания Remarks

Макросы va_arg, va_copy, va_endи va_start предоставляют переносимый способ доступа к аргументам функции, когда функция принимает переменное число аргументов. The va_arg, va_copy, va_end, and va_start macros provide a portable way to access the arguments to a function when the function takes a variable number of arguments. Существует две версии макросов: Макросы, определенные в STDARG. H соответствует стандарту ISO C99; макросы, определенные в списке VARARGS. H не рекомендуется использовать, но они сохраняются для обеспечения обратной совместимости с кодом, написанным до стандарта ANSI C89. There are two versions of the macros: The macros defined in STDARG.H conform to the ISO C99 standard; the macros defined in VARARGS.H are deprecated but are retained for backward compatibility with code that was written before the ANSI C89 standard.

Эти макросы предполагают, что функции принимают фиксированное число обязательных аргументов, за которыми следует переменное число необязательных аргументов. These macros assume that the function takes a fixed number of required arguments, followed by a variable number of optional arguments. Обязательные аргументы объявляются как обычные параметры для функции и доступ к ним возможен через имена параметров. The required arguments are declared as ordinary parameters to the function and can be accessed through the parameter names. Доступ к необязательным аргументам осуществляется через макросы в STDARG.H (или VARARGS.H для кода, написанного до появления стандарта ANSI C89), которые задают указатель на первый необязательный аргумент в списке аргументов, извлекают аргументы из списка и сбрасывают указатель после завершения обработки аргументов. The optional arguments are accessed through the macros in STDARG.H (or VARARGS.H for code that was written before the ANSI C89 standard), which sets a pointer to the first optional argument in the argument list, retrieves arguments from the list, and resets the pointer when argument processing is completed.

Стандартные макросы языка C, которые определены в STDARG.H, используются следующим образом: The C standard macros, defined in STDARG.H, are used as follows:

va_start задает для arg_ptr первый необязательный аргумент в списке аргументов, передаваемых в функцию. va_start sets arg_ptr to the first optional argument in the list of arguments that’s passed to the function. Аргумент arg_ptr должен иметь тип va_list . The argument arg_ptr must have the va_list type. Аргумент prev_param — это имя обязательного параметра, который непосредственно предшествует первому необязательному аргументу в списке аргументов. The argument prev_param is the name of the required parameter that immediately precedes the first optional argument in the argument list. Если prev_param объявлен с классом хранения Register, поведение макроса не определено. If prev_param is declared with the register storage class, the macro’s behavior is undefined. va_start необходимо использовать перед первым использованием va_arg . va_start must be used before va_arg is used for the first time.

va_arg извлекает значение типа из расположения, заданного параметром arg_ptr, и увеличивает arg_ptr , чтобы он указывал на следующий аргумент в списке, используя размер типа , чтобы определить, где начинается следующий аргумент. va_arg retrieves a value of type from the location that’s given by arg_ptr, and increments arg_ptr to point to the next argument in the list by using the size of type to determine where the next argument starts. va_arg можно использовать любое количество раз в функции для получения аргументов из списка. va_arg can be used any number of times in the function to retrieve arguments from the list.

va_copy создает копию списка аргументов в его текущем состоянии. va_copy makes a copy of a list of arguments in its current state. Параметр src уже должен быть инициализирован с помощью va_start; возможно, он был обновлен с помощью вызовов va_arg , но не должен быть сброшен с помощью va_end. The src parameter must already be initialized with va_start; it may have been updated with va_arg calls, but must not have been reset with va_end. Следующий аргумент, полученный va_arg из dest , совпадает со следующим аргументом, полученным из src. The next argument that’s retrieved by va_arg from dest is the same as the next argument that’s retrieved from src.

После получения всех аргументов va_end сбрасывает указатель на null. After all arguments have been retrieved, va_end resets the pointer to NULL. va_end должен вызываться для каждого списка аргументов, который инициализируется с помощью va_start или va_copy перед возвратом функции. va_end must be called on each argument list that’s initialized with va_start or va_copy before the function returns.

Макросы в VARARGS.H использовать не рекомендуется; они сохранены только для обратной совместимости с кодом, который написан до появления стандарта ANSI C89. The macros in VARARGS.H are deprecated and are retained only for backwards compatibility with code that was written before the ANSI C89 standard. Во всех остальных случаях используйте макросы из файла STDARGS.H. In all other cases, use the macros in STDARGS.H.

При компилировании с параметром /clr (компиляция CLR) программы, использующие эти макросы, могут давать непредвиденный результат из-за различий между собственной системой типов и системой типов среды CLR. When they are compiled by using /clr (Common Language Runtime Compilation), programs that use these macros may generate unexpected results because of differences between native and common language runtime (CLR) type systems. Рассмотрим следующую программу: Consider this program:

Обратите внимание, что тестит принимает второй параметр как int или char*. Notice that testit expects its second parameter to be either an int or a char*. Передаваемые аргументы: 0xFFFFFFFF ( Неподписанное целоечисло, не целое число) и null (фактически int, а не char*). The arguments being passed are 0xffffffff (an unsigned int, not an int) and NULL (actually an int, not a char*). Когда программа скомпилирована для неуправляемого кода, она дает следующий результат: When the program is compiled for native code, it produces this output:

Илон Маск рекомендует:  Что такое код swf_lookat

Требования Requirements

Заголовок: и Header: and

Нерекомендуемый заголовок: Deprecated Header:

Как работают функции с переменным числом аргументов в C?

Навеяно вопросом Как работает execlp, что за последний аргумент NULL? Полистал ответы на схожие вопросы, но подробного описания не нашёл:

P.S Предполагается, что читатель этого текста уже выпустился из детсада, и не задаёт вопросов уровня «Мне тут какую-то ошибку выдали, чо это?». И не путает C с C++.

Пинки, подзатыльники и прочие указания на «ты неправ» приветствуются.

1 ответ 1

В языке C есть возможность объявлять и использовать функции с переменным числом аргументов. Возможность эта обеспечивается особенностями работы со стеком при вызове функций, но сейчас они подробно рассматриваться не будут, только практическая сторона вопроса. Магия, происходящая в тоже за рамками, любопытный да найдёт объяснение этому шаманству.

Прототип такой функции может выглядеть так, например:

И печатать, соответственно:

Ну и её реализация:

Самой важной проблемой тут является определение конца списка аргументов. В данном случае использовался NULL для его отметки. Но это не всегда приемлемо. Например, когда NULL является допустимым значением аргумента. Или, скажем, 0 / -1 в случае целых чисел.

Первое решение этой проблемы — передать количество аргументов первым параметром:

Этот метод может применяться только тогда, когда в функцию передаются аргументы одного типа. Того же можно добиться, передавая массив значений с его размером. Но это не всегда оправдано. Да и рассматривается сейчас технологическая демка, а не целесообразность (которая всегда на совести программиста, но на то к нему /dev/brain и прилагается).

Шёпотом: ну и TMTOWTDI в сях тоже бывает, хи-хи.

А что делать, если аргументы могут быть разных типов? Тут на помощь приходит метод под названием «формат». Любой сишник с ним знаком по *printf* . Но это не интересно. Придумаем своё, на том же принципе.

  • символ ‘c’ означает char
  • ‘s’ — short
  • ‘l’ — long
  • ‘z’ — char *


Дальше: char , short и прочее, которое меньше int .

Эти строчки возбуждают компилятор:

Выводы делать не буду, оставлю на домашнее задание.

С++ для начинающих Функции с переменным числом параметров

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

vo >MyFunc (int a ,…) / /Так объявляется функция с заранее неизвестным числом параметров
<

>

vo >main ()
<
system ( “CLS” );
MyFunc ( 100 , 200 , 300 , 400 ); //В функцию передается 4 параметра
system ( “PAUSE” );
>
=========

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

Должен возникнуть вопрос как же получить доступ к каждому из этих параметров. Для того, чтоб хорошо понять то что будет написано, требуется знание указателей. Чтобы иметь доступ к каждому из параметров, нужно знать адрес первого параметра, а чтобы взять этот адрес, как раз и требуется указатель

vo >MyFunc (int a ,…) / /Так объявляется функция с заранее неизвестным числом параметров
<
int * P =& a ; //Взятие адреса у первого параметра

while (* P ) //Пока встречаются параметры
<
cout P ” “ ; //Вытаскиваем значение с адреса по которому живет параметр
P ++; //Адресная арифметика. Смена текущего адреса на следующий
>

>

vo >main ()
<
system ( “CLS” );
MyFunc ( 100 , 200 , 300 , 400 ); //В функцию передается 4 параметра
system ( “PAUSE” );

>

=========
Что можно увидеть? Первым делом внутри функции происходят взятие адреса первого параметра, при этом тип указателя должен совпадать с типом этого параметра. Дальше идет простой перебор всех параметров с помощью цикла.

Таким же образом можно привести классический пример суммирования элементов

vo >MyFunc (double a ,…) / /Так объявляется функция с заранее неизвестным числом параметров
<
double * P =& a ; //Взятие адреса у первого параметра
double sum = 0 ; //Инициализация значения суммы в ноль

while (* P ) //Пока встречаются параметры
<
sum = sum +(* P ) ” “ ; //Прибавляем к сумме то что взяли по адресу P
P ++; //Адресная арифметика. Смена текущего адреса на следующий
>


cout sum endl ; //Вывод результата на экран
>

vo >main ()
<
system ( “CLS” );
MyFunc ( 100.0 , 200.0 , 300.0 , 400.0 ); //В функцию передается 4 параметра
system ( “PAUSE” );

>

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

Даже если типы передаваемых параметров будут различны, то компилятор не выдаст ошибки, но ошибки не выведется только потому что если компилятор видит эти три точки на месте параметров, то он отключает проверку типов. На самом деле легко увидеть эффект небезопасности работы с функцией, в которой указано, что будет более одного параметра, если первый параметр объявить например как int, (соответственно указатель на первый параметр как int), а во время передачи в функцию написать число с точкой (например 1.0 запустить и потом 11.0 и запустить). Т.е. если требуется передать параметры других типов, то их все нужно дописать перед списком предполагаемых неизвестных.
Например vo >MyFunc (float x , char S [],int n ,…), после чего с первыми работать в обычной манере, а с теми что после n с помощью указателя на int и, соответственно, передавать туда параметры с тем же типом, что и у этого n (Исходя из логики того, что тип указателя должен совпадать с типом объекта на адрес которого указатель ссылается).

Но вообще в функцию можно передавать произвольное число параметров с переменным типом, я не говорил, что этого сделать нельзя, можете перечитать всё снова, чтобы в этом убедиться. При определении функций с переменным количеством параметров, рекомендуется использовать специальный набор макроопределений, которые становятся доступными при включении в программу заголовочного файла stdarg.h

Эти макроопределения обеспечивают простой и стандартный (независящий от реализации) способ доступа к спискам параметров переменной длины. Я не буду расписывать, так как сам плохо все это представляю, но приведу пример, содранный с учебника Марченко А.Л. Бархатный путь (2005). Там более менее расписано что к чему и нарушать его авторство я не хочу. Но кое что оттуда вынесу

vo >OK (char * format , …) //Функция OK с произвольным числом параметров
<
va_list ap ;
//Указатель на список параметров
va_start ( ap , format );
//Настроились на список параметров
for (char * p = format ;* p ; p ++) //
<
if (* p ==’ % ‘)
//Если встретится символ %
<
switch (*++ p )
//То анализируем следующий за этим симолом символ
<
case ‘ d ‘: int ival = va_arg ( ap ,int);
//Если это символ d, то значит параметр int
cout ival ” “ ;break;
//Выводим параметр типа int на экран
case ‘ f ‘: double dval = va _ arg ( ap , double );
//Если это символ f значит параметр double
cout dval //Выводим параметр типа double на экран
>
>
else cout p va_end ( ap );
//Завершаем работу с макрокомандами
>

Илон Маск рекомендует:  Циклы в Sass

OK (“ %d%f “, 8 , 9.555 ); //Вывод двух чисел с разными типами
system ( “PAUSE” );
return;
>

====================

  • специальный тип va_list используется для представления списков параметров неизвестной длины и состава
  • va_start вызывается непосредственно перед началом работы с неименованными параметрами
  • ар инициализируется указателем на последний именованный параметр в списке с переменным числом параметров — “параметр” lastarg
  • Здесь под параметр является условным обозначением и относится к макрокомандам, а не функциям
  • После вызова макроопределения va_start, каждый вызов va_arg возвращает значение заказанного типа type себе. Надо заранее указать тип желаемого параметра. В некоторых реализациях с макроопределением va_arg запрещено использовать типы char, unsigned char, float. Даже в макроопределениях, предназначенных для стандартизации языка (речь идет не о Borland C++ 3.1, а о более новых), многое зависит от реализации.
  • Работа со списком параметров завершается вызовом макроопределения vo >va_end ( ap ); Это макроопределение обеспечивает корректный возврат из функции и вызывается перед выходом из функции.

переменные аргументы (va_list va_start) не работают с проходом по ссылке параметра

Привет, у меня есть проблема с переменным числом аргументов. Посмотрите на мой код (Microsoft Visual Studio 2005 или 2008).

Функция Т1, Т2 работают хорошо. Но функция T3 есть проблема. Указатель р указывает не «TEST3». Не могу ли я использовать va_start с выведенным по ссылке? Заранее спасибо.

Вы не можете использовать ссылки с va_start согласно стандарту C ++ 18,7 / 3:

Ограничения, которые ISO C место на втором параметре va_start () макрокоманды в заголовке различны в настоящем стандарте. ParmN параметр является идентификатором крайнего правого параметра в списке переменных параметров определения функции (один раз перед . ). Если parmN параметр объявлен с функцией, массив или ссылочного типа, или с типом, который не совместим с типом, который приводит при прохождении аргумент, для которого не существует ни один параметр, поведение не определено.

Короткий ответ: нет, вы не можете сделать это.


Примечание: я увидел первый ответ, который цитирует стандарт, но я считаю, что стоит показать и мои тесты.

va_start определяется следующим образом:

Визуальная 6: #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )

Визуальная 8: #define _crt_va_start(ap,v) ( __va_start(&ap, _ADDRESSOF(v), _SLOTSIZEOF(v), \ __alignof(v), _ADDRESSOF(v)) )

С помощью этого кода:

Поскольку при реализации ссылка уровня передается на стеке аналогично указатели это представляет собой проблему, поскольку в различене размера (это из-за макрос, который вычисляет размер типа не принимая во внимание, что параметр фактически является ссылка, которая не является постоянной величиной, а зависит от фактического размера типа).

Запись функции для работы с переменным числом параметров

Сейчас я изучаю C и пытаюсь написать свою собственную функцию с переменным количеством параметров, с которыми я хочу работать. Это возможно? Я нашел примеры, как создать такую функцию, но я не знаю, как с ними работать. Вот что я имею:

хорошо в моем оригинальном посте это считалось дубликатом, но я хочу сделать больше, чем просто сделать сумму. Я хочу делать с ним разные вычисления. Как будто я хочу иметь их всех как dA1 для dAn = количество параметров. А потом я хочу делать расчеты.

Попробуйте это (комментарии в строке):

Там ловушка, потому что это недействительно:

Четвертый аргумент ( 50 ) является целым числом. Вы должны убедиться, что вы положили в десятичных литералах, чтобы убедиться, что они добросовестные double .

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

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

Форма записи:

void ИмяФункции (ТипДанных Идентификатор1[, ,ТипДанных ИдентификаторN ,…])

При вызове функции за ИдентификаторомN могут располагаться и другие элементы, если это необходимо. Количество и тип этих элементов не контролируется.

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

Примерами функций с переменным числом параметров являются функции из библиотеки функций языка С++, осуществляющие операции ввода-вывода информации (printf,scanf и т.п.).

Программист может разрабатывать свои функции с переменным числом параметров.

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

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

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

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

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

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

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

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

Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: Только сон приблежает студента к концу лекции. А чужой храп его отдаляет. 8808 — | 7523 — или читать все.

188.64.174.135 © studopedia.ru Не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования. Есть нарушение авторского права? Напишите нам | Обратная связь.

Отключите adBlock!
и обновите страницу (F5)

очень нужно

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL