Reputation: 38574
I understand that the difference between the printf
, fprintf
, sprintf
etc functions and the vprintf
, vfprintf
, vsprintf
etc functions has to do with how they deal with the function arguments. But how specifically? Is there really any reason to use one over the other? Should I just always use printf
as that is a more common thing to see in C, or is there a legitimate reason to pick vprintf
instead?
Upvotes: 60
Views: 31478
Reputation: 1609
This example shows the elegance of Python. Since C/C++ cannot reconcile the difference between int error(char *fmt, ...)
and int error(char *fmt, va_list ap)
, thus, for every function *printf
, it has to create two versions, i.e., one taking in ...
, the other taking in va_list
, this essentially doubles the total number of functions. In Python, you can use *list()
or **dict()
to pass in a va_list
as ...
.
Hopefully, future C/C++ can support this kind of argument processing scheme.
Upvotes: 0
Reputation: 194
The main difficulty with variadic arguments is not that there is a variable number of arguments but that there is no name associated with each argument. The va_start, va_arg macros parse the arguments in memory (in most C compilers they are on the stack) using the type information contained in the format string cf. Kernighan and Ritchie, second edition, section 7.3.
Upvotes: 0
Reputation: 75469
printf()
and friends are for normal use. vprintf()
and friends are for when you want to write your own printf()
-like function. Say you want to write a function to print errors:
int error(char *fmt, ...)
{
int result;
va_list args;
va_start(args, fmt);
// what here?
va_end(args);
return result;
}
You'll notice that you can't pass args
to printf()
, since printf()
takes many arguments, rather than one va_list
argument. The vprintf()
functions, however, do take a va_list
argument instead of a variable number of arguments, so here is the completed version:
int error(char *fmt, ...)
{
int result;
va_list args;
va_start(args, fmt);
fputs("Error: ", stderr);
result = vfprintf(stderr, fmt, args);
va_end(args);
return result;
}
Upvotes: 88
Reputation: 400109
You never want to use vprintf()
directly, but it's incredibly handy when you need to e.g. wrap printf()
. For these cases, you will define the top-level function with variable arguments (...). Then you'll collect those into a va_list
, do your processing, and finally call vprintf()
on the va_list
to get the printout happening.
Upvotes: 17