.\" -*- coding: UTF-8 -*- '\" t .\" Copyright 1990-1991, The Regents of the University of California. .\" Copyright, the authors of the Linux man-pages project .\" .\" SPDX-License-Identifier: BSD-4-Clause-UC .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH stdarg 3 "17 мая 2025 г." "Linux man\-pages 6.18" .SH НАИМЕНОВАНИЕ stdarg, va_start, va_arg, va_end, va_copy \- работа со списком переменного количества аргументов .SH БИБЛИОТЕКА Стандартная библиотека языка C (\fIlibc\fP,\ \fI\-lc\fP) .SH СИНТАКСИС .nf \fB#include \fP .P \fBvoid va_start(va_list \fP\fIap\fP\fB, \fP\fIlast\fP\fB);\fP \fItype\fP\fB va_arg(va_list \fP\fIap\fP\fB, \fP\fItype\fP\fB);\fP \fBvoid va_end(va_list \fP\fIap\fP\fB);\fP \fBvoid va_copy(va_list \fP\fIdest\fP\fB, va_list \fP\fIsrc\fP\fB);\fP .fi .SH ОПИСАНИЕ Функцию можно вызвать передав ей произвольное количество аргументов разных типов. Во включаемом файле \fI\fP объявляется тип \fIva_list\fP и определяется три макроса для пошагового обхода списка аргументов, чьё количество и типы неизвестны вызываемой функции. .P В вызываемой функции требуется объявить объект с типом \fIva_list\fP, который используется макросами \fBva_start\fP(), \fBva_arg\fP() и \fBva_end\fP(). .SS va_start() Макрос \fBva_start\fP() инициализирует \fIap\fP для последующего использования в \fBva_arg\fP()и \fBva_end\fP(), и должен вызываться первым. .P Аргумент \fIlast\fP это имя последнего аргумента перед списком с переменным количеством аргументов, то есть это последний аргумент, тип которого известен вызывающей функции. .P Так как адрес этого аргумента может быть использован в макросе \fBva_start\fP(), он не должен быть объявлен как регистровая переменная, иметь тип функции или массива. .SS va_arg() Макрос \fBva_arg\fP() раскрывается в выражение, которое имеет тип и значение следующего аргумента в вызове. Аргумент \fIap\fP — это \fIva_list\fP \fIap\fP, инициализированный \fBva_start\fP(). Каждый вызов \fBva_arg\fP() изменяет \fIap\fP так, что следующий вызов возвращает следующий аргумент. Аргумент \fItype\fP — это имя типа, указанное так, что тип указателя на объект, который имеет указанный тип, можно получить просто добавив * в \fItype\fP. .P Первый вызов макроса \fBva_arg\fP() после \fBva_start\fP() вернёт аргумент после \fIlast\fP. Последующие вызовы вернут значения оставшихся аргументов. .P Если аргументы закончились, или если \fItype\fP не совместим с типом настоящего следующего аргумента (преобразование происходит согласно преобразованию аргументов по умолчанию), может произойти любая ошибка. .P Если \fIap\fP передан в функцию, которая использует \fBva_arg(\fP\fIap\fP\fB,\fP\fItype\fP\fB),\fP то значение \fIap\fP не определено после возврата из функции. .SS va_end() Каждый использование \fBva_start\fP() должно завершаться соответствующим вызовом \fBva_end\fP() в той же функции. После вызова \fBva_end(\fP\fIap\fP\fB)\fP значение переменной \fIap\fP не определено. Возможно несколько проходов по списку, если каждый из них начинать \fBva_start\fP() и заканчивать \fBva_end\fP(). Макрос \fBva_end\fP() может быть и функцией. .SS va_copy() Макрос \fBva_copy\fP() копирует (ранее инициализированный) список с переменным количеством аргументов \fIsrc\fP в \fIdest\fP. Его действие такое же, как если бы \fBva_start\fP() применили к \fIdest\fP с тем же аргументом \fIlast\fP, после чего было бы совершено такое же количество вызовов \fBva_arg\fP(), которое имеется в текущем состоянии \fIsrc\fP. .P .\" Proposal from clive@demon.net, 1997-02-28 Очевидной реализацией было бы создать переменную с типом \fIva_list\fP, указывающую на стековый фрейм функции с переменным количеством аргументов. В этом случае (безусловно, наиболее распространенном) кажется, что достаточно присвоения .P .in +4n .EX va_list aq = ap; .EE .in .P К сожалению, есть системы, в которых это массив указателей (длиной 1), и нужно делать .P .in +4n .EX va_list aq; *aq = *ap; .EE .in .P Наконец, в системах, где аргументы передаются через регистры, в \fBva_start\fP() может потребоваться выделить память, сохранить там аргументы, а также индекс следующего элемента для того, чтобы \fBva_arg\fP() мог обойти список. Также \fBva_end\fP() может освобождать выделенную память. Чтобы всё это учесть в C99 добавлен макрос \fBva_copy\fP(), который позволяет показанное выше назначение заменить на .P .in +4n .EX va_list aq; va_copy(aq, ap); \&... va_end(aq); .EE .in .P Для каждого вызова \fBva_copy\fP() должен быть соответствующий вызов \fBva_end\fP() в той же функции. В некоторых системах нет \fBva_copy\fP(), а есть \fB__va_copy\fP — имя, которое использовалось в черновике стандарта. .SH АТРИБУТЫ Описание терминов данного раздела смотрите в \fBattributes\fP(7). .TS allbox; lbx lb lb l l l. Интерфейс Атрибут Значение T{ .na .nh \fBva_start\fP(), \fBva_end\fP(), \fBva_copy\fP() T} Безвредность в нитях MT\-Safe T{ .na .nh \fBva_arg\fP() T} Безвредность в нитях MT\-Safe race:ap .TE .SH СТАНДАРТЫ C11, POSIX.1\-2008. .SH ИСТОРИЯ .TP \fBva_start\fP() .TQ \fBva_arg\fP() .TQ \fBva_end\fP() C89, POSIX.1\-2001. .TP \fBva_copy\fP() C99, POSIX.1\-2001. .SH CAVEATS В отличие от исторических макросов \fBvarargs\fP, макросы \fBstdarg\fP не позволяют программистам создать функцию без постоянных аргументов. Эта проблема создаёт работу, в основном, при преобразовании кода \fBvarargs\fP в код \fBstdarg\fP, а также есть сложности с функциями с переменным количеством аргументов, которым нужно передать все их аргументы в функцию в виде аргумента с типом \fIva_list\fP, например \fBvfprintf\fP(3). .SH ПРИМЕРЫ Функция \fIfoo\fP берёт строку с символами формата и печатает аргумент, связанный с каждым таким символом, на основе его типа. .P .EX #include #include \& void foo(char *fmt, ...) /* \[aq]...\[aq] 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 \[aq]s\[aq]: /* string */ s = va_arg(ap, char *); printf("string %s\[rs]n", s); break; case \[aq]d\[aq]: /* int */ d = va_arg(ap, int); printf("int %d\[rs]n", d); break; case \[aq]c\[aq]: /* char */ /* need a cast here since va_arg only takes fully promoted types */ c = (char) va_arg(ap, int); printf("char %c\[rs]n", c); break; } va_end(ap); } .EE .SH "СМОТРИТЕ ТАКЖЕ" \fBvprintf\fP(3), \fBvscanf\fP(3), \fBvsyslog\fP(3) .PP .SH ПЕРЕВОД Русский перевод этой страницы руководства разработал(и) Alexander Golubev , Azamat Hackimov , Hotellook, Nikita , Spiros Georgaras , Vladislav , Yuri Kozlov и Иван Павлов . .PP Этот перевод является свободной программной документацией; он распространяется на условиях общедоступной лицензии GNU (GNU General Public License - GPL, .UR https://www.gnu.org/licenses/gpl-3.0.html .UE версии 3 или более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ. .PP Если вы обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом разработчику(ам) по его(их) адресу(ам) электронной почты или по адресу .MT debian-l10n-russian@lists.debian.org списка рассылки русских переводчиков .ME .