Jump to content

stdarg.h

(Перенаправлено с Va start )

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

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

Объявление вариативных функций

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

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

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

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

char *wrong(...);

не разрешено в C17 и более ранних версиях. (В C++ C23 и [ 2 ] такое объявление разрешено.) В C запятая должна предшествовать многоточию, если указан именованный параметр; в C++ это необязательно.

Определение вариативных функций

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

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

long func(char, double, int, ...);

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

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

типы stdarg.h

[ редактировать ]
Имя Описание Совместимость
va_list тип для итерации аргументов С89

макросы stdarg.h

[ редактировать ]
Имя Описание совместимость
va_start Начните перебор аргументов с помощью va_list С89
va_arg Получить аргумент С89
va_end Бесплатно va_list С89
va_copy Скопируйте содержимое одного va_list другому С99

Доступ к аргументам

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

Чтобы получить доступ к безымянным аргументам, необходимо объявить переменную типа va_list в вариатической функции. Макрос va_start затем вызывается с двумя аргументами: первый — это переменная, объявленная типа va_list, второй — имя последнего именованного параметра функции. В C23 второй аргумент будет необязательным и не будет оцениваться. [ 2 ] После этого каждый вызов va_arg макрос возвращает следующий аргумент. Первый аргумент для va_arg это va_list а второй — тип следующего аргумента, передаваемого функции. Наконец, va_end макрос должен вызываться va_list прежде чем функция вернется. (Не обязательно читать все аргументы.)

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

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

  • Использование printf или scanf-подобная строка формата со встроенными спецификаторами, указывающими типы аргументов.
  • Контрольное значение в конце переменных аргументов.
  • Аргумент-счетчик, указывающий количество аргументов с переменным числом аргументов.

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

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

Поскольку размер списка безымянных аргументов обычно неизвестен (соглашения о вызовах, используемые большинством компиляторов, не позволяют определить размер блока безымянных аргументов, на который указывает 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 *, ни то, ни другое неверно. Еще одним соображением являются повышения аргументов по умолчанию, применяемые к безымянным аргументам. А float будет автоматически повышен до double. Аналогично, аргументы типов, более узких, чем int будет повышен до int или unsigned int. Функция, получающая безымянные аргументы, должна ожидать расширенного типа.

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

format(archetype, string-index, first-to-check)

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

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

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

—  «5.27 Расширения семейства языков C — объявление атрибутов функций» . Проверено 3 января 2009 г.
#include <stdio.h>
#include <stdarg.h>

/* print all args one at a time until a negative argument is seen;
   all args are assumed to be of int type */
void printargs(int arg1, ...)
{
  va_list ap;
  int i;

  va_start(ap, arg1); 
  for (i = arg1; i >= 0; i = va_arg(ap, int))
    printf("%d ", i);
  va_end(ap);
  putchar('\n');
}

int main(void)
{
   printargs(5, 2, 14, 84, 97, 15, -1, 48, -1);
   printargs(84, 51, -1, 3);
   printargs(-1);
   printargs(1, -1);
   return 0;
}

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

5 2 14 84 97 15
84 51

1

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

void MyPrintf(const char *format, ...)
{
  va_list args;
  char buffer[BUFSIZ];

  va_start(args, format);
  vsnprintf(buffer, sizeof buffer, format, args);
  va_end(args);
  FlushFunnyStream(buffer);
}

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

  • его нельзя использовать в стандартных определениях нового стиля C.
  • данный аргумент может быть опущен (стандарт C требует хотя бы один аргумент)

Интерфейс также отличается. Для printargs например, вместо этого можно было бы написать:

#include <stdio.h>
#include <varargs.h>

/* There is no "void" type; use an implicit int return. */
printargs(arg1, va_alist)
  va_dcl /* no semicolon here! */
{
  va_list ap;
  int i;

  va_start(ap); /* only the va_list is given! */
  for (i = arg1; i >= 0; i = va_arg(ap, int))
    printf("%d ", i);
  va_end(ap);
  putchar('\n');
  return;
}

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

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

  1. ^ «IEEE стандарт 1003.1 stdarg.h" Проверено 4 июля 2009 г. .
  2. ^ Перейти обратно: а б Позолота, Алекс; Менейд, Жан Хейд (15 апреля 2022 г.). «WG14-N2975: Ослабьте требования к спискам переменных параметров, версия 3» (PDF) .
  3. ^ «Единая спецификация UNIX varargs.h" Проверено 1 августа 2007 г. .
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 01f8116c3bbdbf73e8a306cb43a9b958__1706096520
URL1:https://arc.ask3.ru/arc/aa/01/58/01f8116c3bbdbf73e8a306cb43a9b958.html
Заголовок, (Title) документа по адресу, URL1:
stdarg.h - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)