0

I want to write a function writelog() with ellipsis parameters, which should forward the same ellipsis parameters to another function. How to do it?

My function example:

void writetolog(char *format, ...)
{
    FILE *file;
    if ((file = fopen(LOG_FILE, "a")) != NULL)
    {
        fprintf(file, format, ...);
        fclose(file);
    }
}

Function fprintf() should have the same ellipsis parameters from function writetolog().

3 Answers3

5

It's not possible, the ... arguments cannot be passed on directly.

What you generally do is implement the lowest layer using an explicit argument list (va_list) argument, and solve it that way.

In your case, if the lowest layer is the standard library's printing, then you need to call vfprintf() with an explicit va_list that holds the arguments to your function:

void writetolog(const char *format, ...)
{
    FILE * const file = fopen(LOG_FILE, "a");
    if (file != NULL)
    {
        va_list args;
        va_start(args, format);
        vfprintf(file, format, args);
        va_end(args);
        fclose(file);
    }
}

Note that in a C macro, you can use the special symbol __VA_ARGS__ to refer to the variable arguments list, but that's not available in functions.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • It is possible, I was doing it once, but I have forgot function name. –  Feb 20 '18 at 10:18
  • 2
    @PeterPolak That sounds a bit like [Fermat](https://en.wikipedia.org/wiki/Fermat%27s_Last_Theorem#Fermat's_conjecture). – unwind Feb 20 '18 at 10:26
4

Use the vfprintf function:

#include <stdarg.h>             // vararg macros

void writetolog(char *format, ...)
{
    FILE *file;
    if ((file = fopen(LOG_FILE, "a")) != NULL)
    {
        va_list args;
        va_start (args, format);

        vfprintf(file, format, args);
        fclose(file);
        va_end(args);
    }
}
Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
  • @spectras, indeed. "_If va_end is not called before returning from the function, the result is undefined._. Fixed that. – Paul Ogilvie Feb 20 '18 at 10:26
0

You can't do it directly; you have to create a function that takes a va_list:

#include <stdarg.h>

static void exampleV(int b, va_list args);

void example(int a, int b, ...)
{
    va_list args;
    va_start(args, b);
    exampleV(b, args);
    va_end(args);
}

void exampleB(int b, ...)
{
    va_list args;
    va_start(args, b);
    exampleV(b, args);
    va_end(args);
}

static void exampleV(int b, va_list args)
{
    ...whatever you planned to have exampleB do...
    ...except it calls neither va_start nor va_end...
}

Taken from Passing variable arguments to another function that accepts a variable argument list