3

many years ago I wrote a custom print function declared like this:

void my_printf(char *format_string, ... )
{
    // too complex to list here
}

and I could call it like this:

my_printf("Number of apples = %d\n",apple);

This function has always worked perfectly. I now wish to make a wrapper function that takes an extra integer at the start like this:

void my_printf_extra(int extra,char *format_string, ... )

that could be called like this:

my_printf_extra(debug_level,"Number of apples = %d\n",apple);

and I would like the wrapper function to call the original in a way something like this:

void my_printf_extra(int extra,char *format_string, ... )
{
    if (extra == some_test)
    {
        my_printf(** not quite sure what goes here **);
    }
}

My guess was this:

void my_printf_extra(int extra,char *format_string, ... )
{
    va_list vptr;

    if (extra == some_test)
    {
        va_start(vptr,format_string);
        my_printf(format_string,vptr);
        va_end(vptr);
    }
}

but it's not working. In my final output I see

Number of apples = -46467968

or some such garbage number (when the true value was 1). I see similar garbage when calling my_printf_extra with a string. I suspect that my processing of va_list is wrong, but I can not fathom how exactly.

EDIT: my_printf() is super flexible and can print to all sorts of different places. Sometimes it just appends the text to a rich-edit-control-window. It all depends on assorted flags as well as the contents of what's being printed.

9
  • Passing the va_list to another function does not fill in the arguments as if they had been passed. A reasonable solution here might be to make the existing my_printf a simpler routine that initializes a va_list and passes it to my_printf_core, which does the rest of the work. Then your my_printf_extra could call my_printf_core instead of my_printf. (my_printf_core could be equivalent to the vfprintf mentioned in the marked original, so essentially the same solution unless you need customizations in my_printf_core.) Commented Jun 28, 2018 at 15:28
  • @Jean-Francois Fabre: I don't see how the duplicate helps. The code is identical to my buggy original. Commented Jun 28, 2018 at 15:31
  • you misread. 1) it's not identical because it's using vfprintf and 2) it works. So there isn't a real solution in the general case, but with printf family functions you can work it out using vfprintf Commented Jun 28, 2018 at 15:33
  • I'm not printing to stdout. The my_printf function is actually rather complex and can print to a variety of different locations or a file or graphically - in assorted colours etc - sometimes more than one location. Dependant on flags Commented Jun 28, 2018 at 15:34
  • are you printing to a file? a buffer? Commented Jun 28, 2018 at 15:35

1 Answer 1

4

Since my_printf doesn't expect a va_list, you can't pass one to it.

This is a case where using a macro makes sense:

#define my_printf_extra(extra, format_string, ... ) \
do {\
    if ((extra) == some_test)\
    {\
        my_printf((format_string), __VA_ARGS__);\
    }\
} while (0)

The __VA_ARGS__ macro replaces all of the extra parameters. Note that this requires a compiler that supports C99.

Alternately, you can modify my_printf to add the extra logic, change the name to something internal, then define my_printf and my_printf_extra as macros that call the internal function:

void my_printf_impl(int extra, char *format_string, ... )
{
    if (extra != some_test) {
        return;
    }

    ...
}

#define EXTRA_DEFAULT 0
#define my_printf(format_string, ...) \
    my_printf_impl(EXTRA_DEFAULT, format_string, __VA_ARGS__)
#define my_printf_extra(extra, format_string, ...) \
    my_printf_impl(extra, format_string, __VA_ARGS__)
Sign up to request clarification or add additional context in comments.

2 Comments

is that compatible with c89?
@Jean-FrançoisFabre I don't believe so. __VA_ARGS__ was introduced with C99.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.