Provided by: manpages-ru-dev_4.27.0-1_all bug

НАИМЕНОВАНИЕ

       stdarg, va_start, va_arg, va_end, va_copy - работа со списком переменного количества аргументов

БИБЛИОТЕКА

       Стандартная библиотека языка C (libc, -lc)

ОБЗОР

       #include <stdarg.h>

       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);

ОПИСАНИЕ

       Функцию  можно  вызвать  передав  ей произвольное количество аргументов разных типов. Во включаемом файле
       <stdarg.h> объявляется тип va_list и определяется три макроса для пошагового  обхода  списка  аргументов,
       чьё количество и типы неизвестны вызываемой функции.

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

   va_start()
       Макрос va_start() инициализирует ap  для  последующего  использования  в  va_arg()и  va_end(),  и  должен
       вызываться первым.

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

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

   va_arg()
       Макрос  va_arg()  раскрывается  в  выражение, которое имеет тип и значение следующего аргумента в вызове.
       Аргумент ap — это va_list ap, инициализированный va_start(). Каждый вызов va_arg() изменяет ap  так,  что
       следующий  вызов  возвращает  следующий  аргумент.  Аргумент  type — это имя типа, указанное так, что тип
       указателя на объект, который имеет указанный тип, можно получить просто добавив * в type.

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

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

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

   va_end()
       Каждый использование va_start() должно завершаться соответствующим вызовом va_end()  в  той  же  функции.
       После вызова va_end(ap) значение переменной ap не определено. Возможно несколько проходов по списку, если
       каждый из них начинать va_start() и заканчивать va_end(). Макрос va_end() может быть и функцией.

   va_copy()
       Макрос  va_copy()  копирует  (ранее  инициализированный) список с переменным количеством аргументов src в
       dest. Его действие такое же, как если бы va_start() применили к dest с тем же аргументом last, после чего
       было бы совершено такое же количество вызовов va_arg(), которое имеется в текущем состоянии src.

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

           va_list aq = ap;

       К сожалению, есть системы, в которых это массив указателей (длиной 1), и нужно делать

           va_list aq;
           *aq = *ap;

       Наконец,  в  системах, где аргументы передаются через регистры, в va_start() может потребоваться выделить
       память, сохранить там аргументы, а также индекс следующего элемента для того, чтобы va_arg()  мог  обойти
       список.  Также  va_end()  может освобождать выделенную память. Чтобы всё это учесть в C99 добавлен макрос
       va_copy(), который позволяет показанное выше назначение заменить на

           va_list aq;
           va_copy(aq, ap);
           ...
           va_end(aq);

       Для каждого вызова va_copy() должен быть соответствующий вызов va_end() в той  же  функции.  В  некоторых
       системах нет va_copy(), а есть __va_copy — имя, которое использовалось в черновике стандарта.

АТРИБУТЫ

       Описание терминов данного раздела смотрите в attributes(7).
       ┌──────────────────────────────────────────────────────────────┬──────────────────────┬─────────────────┐
       │ ИнтерфейсАтрибутЗначение        │
       ├──────────────────────────────────────────────────────────────┼──────────────────────┼─────────────────┤
       │ va_start(), va_end(), va_copy()                              │ Безвредность в нитях │ MT-Safe         │
       ├──────────────────────────────────────────────────────────────┼──────────────────────┼─────────────────┤
       │ va_arg()                                                     │ Безвредность в нитях │ MT-Safe race:ap │
       └──────────────────────────────────────────────────────────────┴──────────────────────┴─────────────────┘

СТАНДАРТЫ

       C11, POSIX.1-2008.

ИСТОРИЯ

       va_start()
       va_arg()
       va_end()
              C89, POSIX.1-2001.

       va_copy()
              C99, POSIX.1-2001.

CAVEATS

       В отличие от исторических макросов varargs, макросы stdarg не позволяют программистам создать функцию без
       постоянных  аргументов.  Эта  проблема  создаёт работу, в основном, при преобразовании кода varargs в код
       stdarg, а также есть сложности с функциями с переменным количеством аргументов,  которым  нужно  передать
       все их аргументы в функцию в виде аргумента с типом va_list, например vfprintf(3).

ПРИМЕРЫ

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

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

       void
       foo(char *fmt, ...)   /* '...' is C syntax for a variadic function */

       {
           va_list ap;
           int d;
           char c;
           char *s;

           va_start(ap, fmt);
           while (*fmt)
               switch (*fmt++) {
               case 's':              /* string */
                   s = va_arg(ap, char *);
                   printf("string %s\n", s);
                   break;
               case 'd':              /* int */
                   d = va_arg(ap, int);
                   printf("int %d\n", d);
                   break;
               case 'c':              /* char */
                   /* need a cast here since va_arg only
                      takes fully promoted types */
                   c = (char) va_arg(ap, int);
                   printf("char %c\n", c);
                   break;
               }
           va_end(ap);
       }

СМОТРИТЕ ТАКЖЕ

       vprintf(3), vscanf(3), vsyslog(3)

ПЕРЕВОД

       Русский перевод этой страницы руководства разработал(и)  Alexander  Golubev  <fatzer2@gmail.com>,  Azamat
       Hackimov   <azamat.hackimov@gmail.com>,   Hotellook,   Nikita   <zxcvbnm3230@mail.ru>,  Spiros  Georgaras
       <sng@hellug.gr>, Vladislav <ivladislavefimov@gmail.com>, Yuri Kozlov  <yuray@komyakino.ru>,  Иван  Павлов
       <pavia00@gmail.com> и Kirill Rekhov <krekhov.dev@gmail.com>

       Этот  перевод является свободной программной документацией; он распространяется на условиях общедоступной
       лицензии GNU (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html  версии  3  или
       более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.

       Если  вы  обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом
       разработчику(ам)  по  его(их)  адресу(ам)  электронной  почты  или  по   адресу   списка рассылки русских
       переводчиков.

Справочные страницы Linux 6.9.1                  15 июня 2024 г.                                       stdarg(3)