stdarg.h - stdarg.h

редактировать

stdarg.h- это заголовок в стандартной библиотеке C файла Язык программирования C, который позволяет функциям принимать неопределенное количество аргументов. Он предоставляет возможности для пошагового просмотра списка аргументов функции неизвестного числа и типа. C ++ предоставляет эту функциональность в заголовке cstdarg.

Содержимое stdarg.hобычно используется в вариационных функциях, хотя их можно использовать в других функциях (например, vprintf ), вызываемых вариативными функциями.

Содержание
  • 1 Объявление вариативных функций
  • 2 Определение вариативных функций
  • 3 типа stdarg.h
  • 4 макроса stdarg.h
  • 5 Доступ к аргументам
    • 5.1 Передача безымянных аргументов другим вызовов
  • 6 Безопасность типов
  • 7 Пример
  • 8 varargs.h
  • 9 Ссылки
Объявление функций с переменным числом аргументов

Функции с переменным числом - это функции, которые могут принимать переменное количество аргументов и являются объявлен с многоточием вместо последнего параметра. Пример такой функции - printf . Типичное объявление -

int check (int a, double b,...);

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

char * error (...);

не допускается в C. (В C ++ такое объявление разрешено). В C запятая должна предшествовать многоточию; в C ++ это необязательно.

Определение функций с переменным числом аргументов

В определении используется тот же синтаксис:

long func (char, double, int,...); long func (char a, double b, int c,...) {/ *... * /}

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

stdarg.h типы
NameОписаниеCompatibility
va_list тип для итерации аргументовC89
макросы stdarg.h
ИмяОписаниесовместимость
va_start Начать итерацию аргументов с va_listC89
va_arg Получить аргументC89
va_end Освободить va_listC89
va_copy Копировать содержимое одного va_listв другойC99
Доступ аргументы

Для доступа к безымянным аргументам необходимо объявить переменную типа va_listв вариативной функции. Затем вызывается макрос va_startс двумя аргументами: первый - это переменная, объявленная с типом va_list, вторая - это имя последнего указанного параметра функции. После этого каждый вызов макроса va_argдает следующий аргумент. Первый аргумент va_arg- это va_list, а второй - тип следующего аргумента, переданного функции. Наконец, перед возвратом функции должен быть вызван макрос va_endв va_list. (Не требуется читать все аргументы.)

C99 предоставляет дополнительный макрос, va_copy, который может дублировать состояние va_list. Вызов макроса va_copy (va2, va1)копирует va1в va2.

. Не определен механизм для определения количества или типов безымянных аргументов, переданных в функцию.. Функция просто обязана каким-то образом знать или определять это, средства для этого могут быть разными. Общие соглашения включают:

  • Использование строки формата printf или scanf со встроенными спецификаторами, указывающими типы аргументов. 140>контрольное значение в конце вариативных аргументов.
  • аргумент счетчика, указывающий количество вариативных аргументов.

Передача безымянных аргументов в другие вызовы

Поскольку размер безымянный список аргументов обычно неизвестен (соглашения о вызовах, используемые большинством компиляторов, не позволяют определять размер безымянного блока аргументов, на который указывает va_listвнутри принимающей функции), также нет надежного универсального способа для пересылки безымянных аргументов в другую вариативную функцию. Даже если определение размера списка аргументов возможно косвенными средствами (например, путем анализа строки формата fprintf ()), нет переносимого способа передать динамически определяемое количество аргументов в внутренний вариативный вызов, поскольку количество и размер аргументов, передаваемых в такие вызовы, обычно должны быть известны во время компиляции. В некоторой степени это ограничение можно ослабить, используя макросы с переменными числами вместо функций с переменными числами. Кроме того, большинство стандартных библиотечных процедур предоставляют альтернативные версии с префиксом v, которые принимают ссылку на безымянный список аргументов (то есть на инициализированную переменную va_list) вместо самого безымянного списка аргументов. Например, vfprintf ()- это альтернативная версия fprintf (), ожидающая va_listвместо фактического безымянного списка аргументов. Поэтому определяемая пользователем вариационная функция может инициализировать переменную va_listс помощью va_startи передать ее соответствующей стандартной библиотечной функции, фактически передавая безымянный список аргументов по ссылке вместо того, чтобы делать это с помощью значение. Поскольку в C не существует надежного способа передачи безымянных списков аргументов по значению, предоставление функций с переменным числом аргументов API без предоставления эквивалентных функций, принимающих вместо этого va_list, считается плохой практикой программирования.

Безопасность типов

Некоторые реализации C предоставляют расширения C, которые позволяют компилятору проверять правильность использования строк формата и контрольных индикаторов. Запрещая эти расширения, компилятор обычно не может проверить, соответствуют ли переданные безымянные аргументы ожидаемому функцией типу, или преобразовать их в требуемый тип. Следовательно, следует позаботиться о том, чтобы гарантировать правильность в этом отношении, поскольку неопределенное поведение возникает, если типы не совпадают. Например, если ожидаемый тип - int *, тогда нулевой указатель должен быть передан как (int *) NULL. Запись только NULLприведет к аргументу типа intили void *, ни один из которых не является правильным. Еще одно соображение - аргумент по умолчанию promotions, применяемый к безымянным аргументам. floatбудет автоматически преобразован в double. Аналогичным образом, аргументы типов, меньших, чем int, будут преобразованы в intили unsigned int. Функция, получающая безымянные аргументы, должна ожидать повышенный тип.

GCC имеет расширение, которое проверяет переданные аргументы:

формат (архетип, строковый индекс, первая проверка)

Атрибут формата указывает, что функция принимает printf, scanf, strftimeили strfmonаргументы стиля, которые должны проверяться на соответствие типу строки формата. Например, объявление:

extern int my_printf (void * my_object, const char * my_format,...) __attribute__ ((format (printf, 2, 3)));

заставляет компилятор проверять аргументы в вызовах my_printfна согласованность с аргументом строки формата стиля printfmy_format.

"5.27 Расширения семейства языков C - Объявление атрибутов функций ». Проверено 3 января 2009 г.
Пример
#include #include / * выводит все аргументы по одному, пока не будет обнаружен отрицательный аргумент; предполагается, что все аргументы имеют тип int * / void printargs (int arg1,...) {va_list ap; int i; va_start (ap, arg1); для (я = arg1; я>= 0; я = va_arg (ap, int)) printf ("% d", я); va_end (ap); путчар ('\ п'); } int main (void) {printargs (5, 2, 14, 84, 97, 15, -1, 48, -1); printargs (84, 51, -1, 3); printargs (-1); printargs (1, -1); возврат 0; }

Эта программа дает результат:

5 2 14 84 97 15 84 51 1

Чтобы вызвать другие функции var args из вашей функции (например, sprintf), вам необходимо использовать версия функции var arg (в данном примере vsprintf):

void MyPrintf (const char * format,...) {va_list args; буфер символов [BUFSIZ]; va_start (аргументы, формат); vsnprintf (буфер, размер буфера, формат, аргументы); va_end (аргументы); FlushFunnyStream (буфер); }
varargs.h

Устаревшие версии POSIX определили унаследованный заголовок varargs.h, который появился еще до стандартизации C и обеспечивает функциональность, аналогичную stdarg.h. Этот заголовок не входит ни в ISO C, ни в POSIX. Файл, как определено во второй версии Single UNIX Specification, просто содержит все функциональные возможности C89 stdarg.h, за исключением следующих: он не может использоваться в стандартных Определения нового стиля C; вы можете отказаться от заданного аргумента (стандартный C требует хотя бы одного аргумента); и способ его работы отличается - в стандартном C можно было бы написать:

#include int summate (int n,...) {va_list ap; int я = 0; va_start (ap, n); для (; n; n--) i + = va_arg (ap, int); va_end (ap); вернуть я; }

и вызовите с

summate (0); summate (1, 2); summate (4, 9, 2, 3, 2);

Для varargs.hфункция будет выглядеть так:

#include summate (n, va_alist) va_dcl / * точки с запятой здесь нет! * / {va_list ap; int я = 0; va_start (ap); для (; n; n--) i + = va_arg (ap, int); va_end (ap); вернуть я; }

и называется так же.

varargs.hтребует определения функций в старом стиле из-за того, как работает реализация. И наоборот, нельзя смешивать определения функций в старом стиле с stdarg.h.

Ссылки
Последняя правка сделана 2021-06-09 10:21:22
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте