stdarg(5) stdarg(5)
stdarg - variable argument list
#include <stdarg.h>
void va_start (va_list ap, ParmN);
type va_arg (va_list ap, type);
void va_end (va_list ap);
This set of macros provides a means of writing portable procedures that
accept variable argument lists. Routines having variable argument lists
(such as printf(3)) that do not use stdarg are inherently nonportable,
since different machines use different argument passing conventions. The
stdarg facility is similar to varargs(5), but is based on the ANSI
Standard for C.
A variable argument list contains one or more parameters. The rightmost
parameter plays a special role, and is designated ParmN in this
discussion.
va_list is a type suitable for storing information needed by the macros
va_start, va_arg, and va_end. The called function must declare a
variable (referred to as ap) of type va_list, used to access the argument
list.
The va_start (ap, ParmN) macro initializes ap for subsequent use by
va_arg and va_end. va_start must be called before any use of va_arg.
The ANSI C Standard (ANSI X3.159-1989) restricts the type of parmN to one
of the types resulting from the default argument promotions, currently
int, unsigned int, pointer, or double. If va_start is invoked with a
parmN which is not one of these types (e.g., if parmN is short or char)
the behavior is undefined.
The va_arg (ap, type) macro will return the next argument in the list
pointed to by ap. The first invocation of va_arg returns the value of
the argument after that specified by ParmN. Successive invocations
return the values of the remaining arguments in succession. type is the
type to which the expected argument will be converted when passed as an
argument, as indicated by the default argument promotions. Thus,
arguments that are char or short should be accessed as int; unsigned char
or unsigned short should be accessed as unsigned int; and float arguments
should be accessed as double. Arguments which are pointers should be
accessed using their own type. Different types can be mixed, but it is
up to the routine to know what type of argument is expected.
va_end (ap) is used to finish up.
Page 1
stdarg(5) stdarg(5)
Multiple traversals, each bracketed by va_start ... va_end, are
possible.
#include <stdarg.h>
#define MAXARGS 31
void f1(int nptrs, ...)
{
va_list ap;
char *array[MAXARGS];
int ptr_no = 0;
if (nptrs > MAXARGS)
nptrs = MAXARGS;
va_start(ap, nptrs);
while (ptr_no < nptrs)
(array[ptr_no++] = va_arg(ap, char *));
va_end(ap);
}
varargs(5)
Due to the procedure calling convention on the MIPS processor, floatingpoint
parameters may be inaccessible via stdarg unless they appear after
a parameter of non-floating-point type. Thus, in the code sequence
extern int foo(float,...);
foo(1.0,2.0);
the parameter 2.0 may be accessed incorrectly. If the function expected
an intervening non-floating-point parameter, such as
extern int foo(float,...);
foo(1.0,4,2.0);
the second floating-point parameter would be accessible as a double. No
problem is encountered, of course, if the type of the first argument is
not floating-point.
Stdarg cannot be used when passing structures as parameters, as it is
impossible to determine their alignment at runtime.
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, execl passes a 0 to signal the end of the list. Printf can
tell how many arguments are supposed to be there by the format.
The macros va_start and va_end may be arbitrarily complex; for example,
va_start might contain an opening brace, which is closed by a matching
brace in va_end. Thus, they should only be used where they could be
placed within a single complex statement.
PPPPaaaaggggeeee 2222 [ Back ]
|