The functions vprintf
and friends are provided so that you can define your own variadic printf
-like functions that make use of the same internals as the built-in formatted output functions.
The most natural way to define such functions would be to use a language construct to say, ``Call printf
and pass this template plus all of my arguments after the first five.'' But there is no way to do this in C, and it would be hard to provide a way, since at the C language level there is no way to tell how many arguments your function received.
Since that method is impossible, we provide alternative functions, the vprintf
series, which lets you pass a va_list
to describe ``all of my arguments after the first five.''
Before calling vprintf
or the other functions listed in this section, you must call va_start
(see Variadic Functions) to initialize a pointer to the variable arguments. Then you can call va_arg
to fetch the arguments that you want to handle yourself. This advances the pointer past those arguments.
Once your va_list
pointer is pointing at the argument of your choice, you are ready to call vprintf
. That argument and all subsequent arguments that were passed to your function are used by vprintf
along with the template that you specified separately.
In some other systems, the va_list
pointer may become invalid after the call to vprintf
, so you must not use va_arg
after you call vprintf
. Instead, you should call va_end
to retire the pointer from service. However, you can safely call va_start
on another pointer variable and begin fetching the arguments again through that pointer. Calling vprintf
does not destroy the argument list of your function, merely the particular pointer that you passed to it.
GNU C does not have such restrictions. You can safely continue to fetch arguments from a va_list
pointer after passing it to vprintf
, and va_end
is a no-op. (Note, however, that subsequent va_arg
calls will fetch the same arguments which vprintf
previously used.)
Prototypes for these functions are declared in `stdio.h'.
printf
except that, instead of taking a variable number of arguments directly, it takes an argument list pointer ap.
fprintf
with the variable argument list specified directly as for vprintf
.
sprintf
with the variable argument list specified directly as for vprintf
.
snprintf
with the variable argument list specified directly as for vprintf
.
vasprintf
function is the equivalent of asprintf
with the variable argument list specified directly as for vprintf
.
obstack_vprintf
function is the equivalent of obstack_printf
with the variable argument list specified directly as for vprintf
.
Here's an example showing how you might use vfprintf
. This is a function that prints error messages to the stream stderr
, along with a prefix indicating the name of the program (see Error Messages, for a description of program_invocation_short_name
).
#include <stdio.h> #include <stdarg.h> void eprintf (const char *template, ...) { va_list ap; extern char *program_invocation_short_name; fprintf (stderr, "%s: ", program_invocation_short_name); va_start (ap, count); vfprintf (stderr, template, ap); va_end (ap); }
You could call eprintf
like this:
eprintf ("file `%s' does not exist\n", filename);
In GNU C, there is a special construct you can use to let the compiler know that a function uses a printf
-style format string. Then it can check the number and types of arguments in each call to the function, and warn you when they do not match the format string. For example, take this declaration of eprintf
:
void eprintf (const char *template, ...) __attribute__ ((format (printf, 1, 2)));
This tells the compiler that eprintf
uses a format string like printf
(as opposed to scanf
; see Formatted Input); the format string appears as the first argument; and the arguments to satisfy the format begin with the second. See Declaring Attributes of Functions, for more information.