1

I'm interested in using function(specifier, ...); style variable-parameter functions in C for other purposes than fancy printing or specified format readout.

Examples may include custom database columns, passing variable parameters to functions that can serialize them depending on content, and many others.

I know of the basic use:

char buffer[BUF_SIZE]
va_list args;
va_start(args, format);
vsnprintf(buffer, BUF_SIZE-1, format, args);
va_end(args);

This is not what I'm asking about.

Lets imagine I want to cook my own printf, which uses vastly different format, say, instead of format string it uses format list - an array of enums specifying types, or some other way to specify what exactly is being loaded into the ... - nothing even register_printf_function-> could help me with, and for one reason or another I'm unwilling to try to build a format string from the data provided.

So, how would I go about accessing the data from the extra ellipsis (instead of passing it blindly to a magical vprintf without ever peering inside it)?

Community
  • 1
  • 1
SF.
  • 13,549
  • 14
  • 71
  • 107

2 Answers2

4

You use va_arg:

va_list ap;
va_start(ap, specifier);  // the argument before the ellipsis

int i = va_arg(ap, int);  // extract an int argument
double d = va_arg(ap, double);  // extract a double argument
// etcetera.

va_end(ap);  // cleanup

Online example showing how to use va_arg with structure types and a sentinel for termination.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • Could you elaborate? e.g. how do I iterate over multiple arguments? Can I reach ahead to n-th argument? Am I limited to primitive types or can I extract custom structs etc? – SF. Sep 09 '14 at 13:06
  • @SF. you read one argument at a time. There are officially no restrictions on extracting structure types, although I'm not entirely sure how portable that is. – ecatmur Sep 09 '14 at 13:08
1

Just to point out, as you can see in the examples provided, you are bound to use static typing with va_arg:

int i = va_arg(ap, int);

Of course you could use some common interface for the parameters and then deduce the actual type from it, but as an alternative you can look at variadic templates. Here is a good post actually talking about the benefits of variadic templates over va_args.

Community
  • 1
  • 1
Rudolfs Bundulis
  • 11,636
  • 6
  • 33
  • 71