4

I'm trying to write a basic macro like this:

#define USER_ERROR(fmt, ...) { \
    fprintf(stderr, "ERROR %s(): %s\n", __func__, fmt, ##__VA_ARGS__); \
} \

my ideal usage:

USER_ERROR("something went wrong %s %s", more_detail, even_more_detail);

unfortunately, I'm getting a compilation error:

data argument not used by format string

I know that single %s handles one argument, but how can I make the formatter variadic?

Ken White
  • 123,280
  • 14
  • 225
  • 444
kamkow1
  • 467
  • 2
  • 8
  • You can't "nest" format specifiers: it isn't recursive. The string you supplied for `%s` can't itself contain format specifiers (that will be interpreted). – Weather Vane Nov 02 '22 at 23:00

1 Answers1

3

You can use string constant concatenation to combine your format string with the built-in one in your macro:

#define USER_ERROR(fmt, ...) \
    fprintf(stderr, "ERROR %s(): " fmt "\n", __func__, ##__VA_ARGS__);

int main()
{
    char more_detail[]="abc", even_more_detail[]="def";
    USER_ERROR("something went wrong %s %s", more_detail, even_more_detail);
    return 0;
}

Output:

ERROR main(): something went wrong abc def

This also has the side effect of ensuring that your format string is a string constant, as having a format string potentially under the control of a user can lead to security issues.

dbush
  • 205,898
  • 23
  • 218
  • 273