stdarg(5) stdarg(5) NAME stdarg - variable argument list SYNOPSIS #include <stdarg.h> void va_start (va_list ap, ParmN); type va_arg (va_list ap, type); void va_end (va_list ap); DESCRIPTION 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. Multiple traversals, each bracketed by va_start ... va_end, are possible. EXAMPLE #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); } SEE ALSO varargs(5) BUGS Due to the procedure calling convention on the MIPS processor, floating- point 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. Page 2