Variadic Arguments in C Macros

It is possible to wrap a variadic function in C, using some facilities provided by C99 (as supported by GCC and a couple of other compilers). This may be helpful for instance if you need to customize the way you are logging events.

Example

We will try to define our own logger using vfprintf, adding the line and file to the output, using the following macro:

#define LOG(...)        log_print(__LINE__, __FILE__, __VA_ARGS__)

The list of argument used when calling LOG can be of an undefined size, and will be textually replaced by the __VA_ARGS__ macro. That means the following lines produce the same result:

LOG("the answer to life is %d", 42);
log_print(__LINE__, __FILE__, "the answer to life is %d", 42);

Implementation

Let’s implement the log_print function, a simple printf wrapper:

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
 
int
log_print(int line, char *file, char *fmt, ...)
{
  va_list       ap;
 
  fprintf(stdout, "[%s - line %d] ", file, line);
  va_start(ap, fmt);
  vfprintf(stdout, fmt, ap);
  va_end(ap);
  fprintf(stdout, "\n");
 
  return 0;
}

Result

Now we can log our debugs with informations about location of the problem, as if we were using a standard printf call:

#include <stdio.h>
#include <errno.h>
#include <string.h>
 
#define LOG(...)        log_print(__LINE__, __FILE__, __VA_ARGS__)
 
int
main(void)
{
    FILE *fh;
 
    if ((fh = fopen("bleh", "r")) == NULL)
        LOG("unable to open file [%s] : %s", bleh, strerror(errno));
    else
        fclose(fh);
 
    return (0);
}

An example of output:

$ ./a.out 
[test.c - line 35] unable to open file [/bleh] : No such file or directory