Blame man3/stdarg.3

Packit 7cfc04
.\" Copyright (c) 1990, 1991 The Regents of the University of California.
Packit 7cfc04
.\" All rights reserved.
Packit 7cfc04
.\"
Packit 7cfc04
.\" This code is derived from software contributed to Berkeley by
Packit 7cfc04
.\" the American National Standards Committee X3, on Information
Packit 7cfc04
.\" Processing Systems.
Packit 7cfc04
.\"
Packit 7cfc04
.\" %%%LICENSE_START(BSD_4_CLAUSE_UCB)
Packit 7cfc04
.\" Redistribution and use in source and binary forms, with or without
Packit 7cfc04
.\" modification, are permitted provided that the following conditions
Packit 7cfc04
.\" are met:
Packit 7cfc04
.\" 1. Redistributions of source code must retain the above copyright
Packit 7cfc04
.\"    notice, this list of conditions and the following disclaimer.
Packit 7cfc04
.\" 2. Redistributions in binary form must reproduce the above copyright
Packit 7cfc04
.\"    notice, this list of conditions and the following disclaimer in the
Packit 7cfc04
.\"    documentation and/or other materials provided with the distribution.
Packit 7cfc04
.\" 3. All advertising materials mentioning features or use of this software
Packit 7cfc04
.\"    must display the following acknowledgement:
Packit 7cfc04
.\"	This product includes software developed by the University of
Packit 7cfc04
.\"	California, Berkeley and its contributors.
Packit 7cfc04
.\" 4. Neither the name of the University nor the names of its contributors
Packit 7cfc04
.\"    may be used to endorse or promote products derived from this software
Packit 7cfc04
.\"    without specific prior written permission.
Packit 7cfc04
.\"
Packit 7cfc04
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
Packit 7cfc04
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit 7cfc04
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 7cfc04
.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
Packit 7cfc04
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit 7cfc04
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Packit 7cfc04
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit 7cfc04
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit 7cfc04
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Packit 7cfc04
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Packit 7cfc04
.\" SUCH DAMAGE.
Packit 7cfc04
.\" %%%LICENSE_END
Packit 7cfc04
.\"
Packit 7cfc04
.\"	@(#)stdarg.3	6.8 (Berkeley) 6/29/91
Packit 7cfc04
.\"
Packit 7cfc04
.\" Converted for Linux, Mon Nov 29 15:11:11 1993, faith@cs.unc.edu
Packit 7cfc04
.\" Additions, 2001-10-14, aeb
Packit 7cfc04
.\"
Packit 7cfc04
.TH STDARG 3  2017-09-15 "" "Linux Programmer's Manual"
Packit 7cfc04
.SH NAME
Packit 7cfc04
stdarg, va_start, va_arg, va_end, va_copy \- variable argument lists
Packit 7cfc04
.SH SYNOPSIS
Packit 7cfc04
.B #include <stdarg.h>
Packit 7cfc04
.PP
Packit 7cfc04
.BI "void va_start(va_list " ap ", " last );
Packit 7cfc04
.br
Packit 7cfc04
.IB type " va_arg(va_list " ap ", " type );
Packit 7cfc04
.br
Packit 7cfc04
.BI "void va_end(va_list " ap );
Packit 7cfc04
.br
Packit 7cfc04
.BI "void va_copy(va_list " dest ", va_list " src );
Packit 7cfc04
.SH DESCRIPTION
Packit 7cfc04
A function may be called with a varying number of arguments of varying
Packit 7cfc04
types.
Packit 7cfc04
The include file
Packit 7cfc04
.I <stdarg.h>
Packit 7cfc04
declares a type
Packit 7cfc04
.I va_list
Packit 7cfc04
and defines three macros for stepping through a list of arguments whose
Packit 7cfc04
number and types are not known to the called function.
Packit 7cfc04
.PP
Packit 7cfc04
The called function must declare an object of type
Packit 7cfc04
.I va_list
Packit 7cfc04
which is used by the macros
Packit 7cfc04
.BR va_start (),
Packit 7cfc04
.BR va_arg (),
Packit 7cfc04
and
Packit 7cfc04
.BR va_end ().
Packit 7cfc04
.SS va_start()
Packit 7cfc04
The
Packit 7cfc04
.BR va_start ()
Packit 7cfc04
macro initializes
Packit 7cfc04
.I ap
Packit 7cfc04
for subsequent use by
Packit 7cfc04
.BR va_arg ()
Packit 7cfc04
and
Packit 7cfc04
.BR va_end (),
Packit 7cfc04
and must be called first.
Packit 7cfc04
.PP
Packit 7cfc04
The argument
Packit 7cfc04
.I last
Packit 7cfc04
is the name of the last argument before the variable argument list, that is,
Packit 7cfc04
the last argument of which the calling function knows the type.
Packit 7cfc04
.PP
Packit 7cfc04
Because the address of this argument may be used in the
Packit 7cfc04
.BR va_start ()
Packit 7cfc04
macro, it should not be declared as a register variable,
Packit 7cfc04
or as a function or an array type.
Packit 7cfc04
.SS va_arg()
Packit 7cfc04
The
Packit 7cfc04
.BR va_arg ()
Packit 7cfc04
macro expands to an expression that has the type and value of the next
Packit 7cfc04
argument in the call.
Packit 7cfc04
The argument
Packit 7cfc04
.I ap
Packit 7cfc04
is the
Packit 7cfc04
.I va_list
Packit 7cfc04
.I ap
Packit 7cfc04
initialized by
Packit 7cfc04
.BR va_start ().
Packit 7cfc04
Each call to
Packit 7cfc04
.BR va_arg ()
Packit 7cfc04
modifies
Packit 7cfc04
.I ap
Packit 7cfc04
so that the next call returns the next argument.
Packit 7cfc04
The argument
Packit 7cfc04
.I type
Packit 7cfc04
is a type name specified so that the type of a pointer to an object that
Packit 7cfc04
has the specified type can be obtained simply by adding a * to
Packit 7cfc04
.IR type .
Packit 7cfc04
.PP
Packit 7cfc04
The first use of the
Packit 7cfc04
.BR va_arg ()
Packit 7cfc04
macro after that of the
Packit 7cfc04
.BR va_start ()
Packit 7cfc04
macro returns the argument after
Packit 7cfc04
.IR last .
Packit 7cfc04
Successive invocations return the values of the remaining arguments.
Packit 7cfc04
.PP
Packit 7cfc04
If there is no next argument, or if
Packit 7cfc04
.I type
Packit 7cfc04
is not compatible with the type of the actual next argument (as promoted
Packit 7cfc04
according to the default argument promotions), random errors will occur.
Packit 7cfc04
.PP
Packit 7cfc04
If
Packit 7cfc04
.I ap
Packit 7cfc04
is passed to a function that uses
Packit 7cfc04
.BI va_arg( ap , type ),
Packit 7cfc04
then the value of
Packit 7cfc04
.I ap
Packit 7cfc04
is undefined after the return of that function.
Packit 7cfc04
.SS va_end()
Packit 7cfc04
Each invocation of
Packit 7cfc04
.BR va_start ()
Packit 7cfc04
must be matched by a corresponding invocation of
Packit 7cfc04
.BR va_end ()
Packit 7cfc04
in the same function.
Packit 7cfc04
After the call
Packit 7cfc04
.BI va_end( ap )
Packit 7cfc04
the variable
Packit 7cfc04
.I ap
Packit 7cfc04
is undefined.
Packit 7cfc04
Multiple traversals of the list, each
Packit 7cfc04
bracketed by
Packit 7cfc04
.BR va_start ()
Packit 7cfc04
and
Packit 7cfc04
.BR va_end ()
Packit 7cfc04
are possible.
Packit 7cfc04
.BR va_end ()
Packit 7cfc04
may be a macro or a function.
Packit 7cfc04
.SS va_copy()
Packit 7cfc04
The
Packit 7cfc04
.BR va_copy ()
Packit 7cfc04
macro copies the (previously initialized) variable argument list
Packit 7cfc04
.I src
Packit 7cfc04
to
Packit 7cfc04
.IR dest .
Packit 7cfc04
The behavior is as if
Packit 7cfc04
.BR va_start ()
Packit 7cfc04
were applied to
Packit 7cfc04
.IR dest
Packit 7cfc04
with the same
Packit 7cfc04
.I last
Packit 7cfc04
argument, followed by the same number of
Packit 7cfc04
.BR va_arg ()
Packit 7cfc04
invocations that was used to reach the current state of
Packit 7cfc04
.IR src .
Packit 7cfc04
.PP
Packit 7cfc04
.\" Proposal from clive@demon.net, 1997-02-28
Packit 7cfc04
An obvious implementation would have a
Packit 7cfc04
.I va_list
Packit 7cfc04
be a pointer to the stack frame of the variadic function.
Packit 7cfc04
In such a setup (by far the most common) there seems
Packit 7cfc04
nothing against an assignment
Packit 7cfc04
.PP
Packit 7cfc04
.in +4n
Packit 7cfc04
.EX
Packit 7cfc04
va_list aq = ap;
Packit 7cfc04
.EE
Packit 7cfc04
.in
Packit 7cfc04
.PP
Packit 7cfc04
Unfortunately, there are also systems that make it an
Packit 7cfc04
array of pointers (of length 1), and there one needs
Packit 7cfc04
.PP
Packit 7cfc04
.in +4n
Packit 7cfc04
.EX
Packit 7cfc04
va_list aq;
Packit 7cfc04
*aq = *ap;
Packit 7cfc04
.EE
Packit 7cfc04
.in
Packit 7cfc04
.PP
Packit 7cfc04
Finally, on systems where arguments are passed in registers,
Packit 7cfc04
it may be necessary for
Packit 7cfc04
.BR va_start ()
Packit 7cfc04
to allocate memory, store the arguments there, and also
Packit 7cfc04
an indication of which argument is next, so that
Packit 7cfc04
.BR va_arg ()
Packit 7cfc04
can step through the list.
Packit 7cfc04
Now
Packit 7cfc04
.BR va_end ()
Packit 7cfc04
can free the allocated memory again.
Packit 7cfc04
To accommodate this situation, C99 adds a macro
Packit 7cfc04
.BR va_copy (),
Packit 7cfc04
so that the above assignment can be replaced by
Packit 7cfc04
.PP
Packit 7cfc04
.in +4n
Packit 7cfc04
.EX
Packit 7cfc04
va_list aq;
Packit 7cfc04
va_copy(aq, ap);
Packit 7cfc04
\&...
Packit 7cfc04
va_end(aq);
Packit 7cfc04
.EE
Packit 7cfc04
.in
Packit 7cfc04
.PP
Packit 7cfc04
Each invocation of
Packit 7cfc04
.BR va_copy ()
Packit 7cfc04
must be matched by a corresponding invocation of
Packit 7cfc04
.BR va_end ()
Packit 7cfc04
in the same function.
Packit 7cfc04
Some systems that do not supply
Packit 7cfc04
.BR va_copy ()
Packit 7cfc04
have
Packit 7cfc04
.B __va_copy
Packit 7cfc04
instead, since that was the name used in the draft proposal.
Packit 7cfc04
.SH ATTRIBUTES
Packit 7cfc04
For an explanation of the terms used in this section, see
Packit 7cfc04
.BR attributes (7).
Packit 7cfc04
.TS
Packit 7cfc04
allbox;
Packit 7cfc04
lbw21 lb lb
Packit 7cfc04
l l l.
Packit 7cfc04
Interface	Attribute	Value
Packit 7cfc04
T{
Packit 7cfc04
.BR va_start (),
Packit 7cfc04
.BR va_end (),
Packit 7cfc04
.BR va_copy ()
Packit 7cfc04
T}	Thread safety	MT-Safe
Packit 7cfc04
T{
Packit 7cfc04
.BR va_arg ()
Packit 7cfc04
T}	Thread safety	MT-Safe race:ap
Packit 7cfc04
.TE
Packit 7cfc04
.SH CONFORMING TO
Packit 7cfc04
The
Packit 7cfc04
.BR va_start (),
Packit 7cfc04
.BR va_arg (),
Packit 7cfc04
and
Packit 7cfc04
.BR va_end ()
Packit 7cfc04
macros conform to C89.
Packit 7cfc04
C99 defines the
Packit 7cfc04
.BR va_copy ()
Packit 7cfc04
macro.
Packit 7cfc04
.SH NOTES
Packit 7cfc04
These macros are
Packit 7cfc04
.I not
Packit 7cfc04
compatible with the historic macros they replace.
Packit 7cfc04
A backward-compatible version can be found in the include file
Packit 7cfc04
.IR <varargs.h> .
Packit 7cfc04
.PP
Packit 7cfc04
The historic setup is:
Packit 7cfc04
.PP
Packit 7cfc04
.in +4n
Packit 7cfc04
.EX
Packit 7cfc04
#include <varargs.h>
Packit 7cfc04
Packit 7cfc04
void
Packit 7cfc04
foo(va_alist)
Packit 7cfc04
    va_dcl
Packit 7cfc04
{
Packit 7cfc04
    va_list ap;
Packit 7cfc04
Packit 7cfc04
    va_start(ap);
Packit 7cfc04
    while (...) {
Packit 7cfc04
        ...
Packit 7cfc04
        x = va_arg(ap, type);
Packit 7cfc04
        ...
Packit 7cfc04
    }
Packit 7cfc04
    va_end(ap);
Packit 7cfc04
}
Packit 7cfc04
.EE
Packit 7cfc04
.in
Packit 7cfc04
.PP
Packit 7cfc04
On some systems,
Packit 7cfc04
.I va_end
Packit 7cfc04
contains a closing \(aq}\(aq matching a \(aq{\(aq in
Packit 7cfc04
.IR va_start ,
Packit 7cfc04
so that both macros must occur in the same function, and in a way
Packit 7cfc04
that allows this.
Packit 7cfc04
.SH BUGS
Packit 7cfc04
Unlike the
Packit 7cfc04
.B varargs
Packit 7cfc04
macros, the
Packit 7cfc04
.B stdarg
Packit 7cfc04
macros do not permit programmers to code a function with no fixed
Packit 7cfc04
arguments.
Packit 7cfc04
This problem generates work mainly when converting
Packit 7cfc04
.B varargs
Packit 7cfc04
code to
Packit 7cfc04
.B stdarg
Packit 7cfc04
code, but it also creates difficulties for variadic functions that wish to
Packit 7cfc04
pass all of their arguments on to a function that takes a
Packit 7cfc04
.I va_list
Packit 7cfc04
argument, such as
Packit 7cfc04
.BR vfprintf (3).
Packit 7cfc04
.SH EXAMPLE
Packit 7cfc04
The function
Packit 7cfc04
.I foo
Packit 7cfc04
takes a string of format characters and prints out the argument associated
Packit 7cfc04
with each format character based on the type.
Packit 7cfc04
.PP
Packit 7cfc04
.EX
Packit 7cfc04
#include <stdio.h>
Packit 7cfc04
#include <stdarg.h>
Packit 7cfc04
Packit 7cfc04
void
Packit 7cfc04
foo(char *fmt, ...)
Packit 7cfc04
{
Packit 7cfc04
    va_list ap;
Packit 7cfc04
    int d;
Packit 7cfc04
    char c, *s;
Packit 7cfc04
Packit 7cfc04
    va_start(ap, fmt);
Packit 7cfc04
    while (*fmt)
Packit 7cfc04
        switch (*fmt++) {
Packit 7cfc04
        case \(aqs\(aq:              /* string */
Packit 7cfc04
            s = va_arg(ap, char *);
Packit 7cfc04
            printf("string %s\en", s);
Packit 7cfc04
            break;
Packit 7cfc04
        case \(aqd\(aq:              /* int */
Packit 7cfc04
            d = va_arg(ap, int);
Packit 7cfc04
            printf("int %d\en", d);
Packit 7cfc04
            break;
Packit 7cfc04
        case \(aqc\(aq:              /* char */
Packit 7cfc04
            /* need a cast here since va_arg only
Packit 7cfc04
               takes fully promoted types */
Packit 7cfc04
            c = (char) va_arg(ap, int);
Packit 7cfc04
            printf("char %c\en", c);
Packit 7cfc04
            break;
Packit 7cfc04
        }
Packit 7cfc04
    va_end(ap);
Packit 7cfc04
}
Packit 7cfc04
.EE
Packit 7cfc04
.SH COLOPHON
Packit 7cfc04
This page is part of release 4.15 of the Linux
Packit 7cfc04
.I man-pages
Packit 7cfc04
project.
Packit 7cfc04
A description of the project,
Packit 7cfc04
information about reporting bugs,
Packit 7cfc04
and the latest version of this page,
Packit 7cfc04
can be found at
Packit 7cfc04
\%https://www.kernel.org/doc/man\-pages/.