124 lines
3 KiB
Groff
124 lines
3 KiB
Groff
|
.\" @(#)varargs.3 6.3 (Berkeley) 5/15/86
|
||
|
.\"
|
||
|
.TH STDARG 3 "May 15, 1986"
|
||
|
.AT 3
|
||
|
.SH NAME
|
||
|
stdarg \- variable argument list
|
||
|
.SH SYNOPSIS
|
||
|
.nf
|
||
|
.ft B
|
||
|
#include <stdarg.h>
|
||
|
|
||
|
void va_start(va_list \fIap\fP, \fIargtypeN\fP \fIparmN\fP)
|
||
|
\fItype\fP va_arg(va_list \fIap\fP, \fItype\fP)
|
||
|
void va_end(va_list \fIap\fP)
|
||
|
.ft R
|
||
|
.fi
|
||
|
.SH DESCRIPTION
|
||
|
This set of macros provides a means of writing portable procedures that
|
||
|
accept variable argument lists.
|
||
|
Routines having variable argument lists (such as
|
||
|
.BR printf (3))
|
||
|
that do not use
|
||
|
.B stdarg
|
||
|
are inherently nonportable, since different
|
||
|
machines use different argument passing conventions.
|
||
|
.PP
|
||
|
A function that accepts a variable argument list is declared with "..." at
|
||
|
the end of its parameter list. It must have at least one normal argument
|
||
|
before the "...". For example:
|
||
|
.PP
|
||
|
.RS
|
||
|
.nf
|
||
|
int printf(const char *format, ...) { /* code */ }
|
||
|
int fprintf(FILE *stream, const char *format, ...) { /* code */ }
|
||
|
.fi
|
||
|
.RE
|
||
|
.PP
|
||
|
.B va_list
|
||
|
is a type which is used for the variable
|
||
|
.I ap
|
||
|
within the body of a variable argument function which is used to traverse
|
||
|
the list.
|
||
|
.PP
|
||
|
.B va_start\c
|
||
|
.RI ( ap ,
|
||
|
.IR parmN )
|
||
|
is called to initialize
|
||
|
.I ap
|
||
|
to the beginning of the list. The last true parameter of the function,
|
||
|
.IR parmN ,
|
||
|
must be supplied to allow
|
||
|
.B va_start
|
||
|
to compute the address of the first variable parameter.
|
||
|
.PP
|
||
|
.B va_arg\c
|
||
|
.RI ( ap ,
|
||
|
.IR type )
|
||
|
will return the next argument in the list pointed to by
|
||
|
.IR ap .
|
||
|
.I Type
|
||
|
is the type to which the expected argument will be converted
|
||
|
when passed as an argument.
|
||
|
.PP
|
||
|
Different types can be mixed, but it is up
|
||
|
to the routine to know what type of argument is
|
||
|
expected, since it cannot be determined at runtime.
|
||
|
.PP
|
||
|
.B va_end\c
|
||
|
.RI ( ap )
|
||
|
must be used to finish up.
|
||
|
.PP
|
||
|
Multiple traversals, each bracketed by
|
||
|
.B va_start
|
||
|
\&...
|
||
|
.B va_end,
|
||
|
are possible.
|
||
|
.SH EXAMPLE
|
||
|
.nf
|
||
|
.ta +4n +4n +4n +4n
|
||
|
\fB#include\fP <stdarg.h>
|
||
|
.sp 0.4
|
||
|
execl(\fBconst char\fP *path, \fB...\fP)
|
||
|
{
|
||
|
\fBva_list\fP ap;
|
||
|
\fBchar\fP *args[100];
|
||
|
\fBint\fP argno = 0;
|
||
|
|
||
|
\fBva_start\fP(ap, path);
|
||
|
\fBwhile\fP ((args[argno++] = \fBva_arg\fP(ap, \fBchar\fP *)) != NULL) {}
|
||
|
\fBva_end\fP(ap);
|
||
|
\fBreturn\fP execv(path, args);
|
||
|
}
|
||
|
.DT
|
||
|
.fi
|
||
|
.SH NOTES
|
||
|
It is up to the calling routine to determine how many arguments
|
||
|
there are, since it is not possible to determine this from the
|
||
|
stack frame. For example,
|
||
|
.B execl
|
||
|
passes a null pointer to signal the end of the list.
|
||
|
.B Printf
|
||
|
can tell how many arguments are supposed to be there by the format.
|
||
|
.PP
|
||
|
The macros
|
||
|
.B va_start
|
||
|
and
|
||
|
.B va_end
|
||
|
may be arbitrarily complex;
|
||
|
for example,
|
||
|
.B va_start
|
||
|
might contain an opening brace,
|
||
|
which is closed by a matching brace in
|
||
|
.BR va_end .
|
||
|
Thus, they should only be used where they could
|
||
|
be placed within a single complex statement.
|
||
|
.SH BUGS
|
||
|
It is impossible to properly show the macros as C declarations as is
|
||
|
done in the synopsis. They can never be coded as C functions, because
|
||
|
all three macros use their arguments by address, and the
|
||
|
.I type
|
||
|
field is certainly impossible.
|
||
|
Just look at them as being part of the C language, like
|
||
|
.BR sizeof .
|