I'm looking to write what I would imagine is a fairly common macro. I want to emulate the repeated "-v" options on many POSIX programs by defining a bunch of macros of the following form:
#define V1(str, ...) if(optv >= 1){printf("%s: "str,prog,__VA_ARGS__);}
int main(int argc, char* argv[])
{
// ... stuff ...
int i = 1;
V1("This contains a variable: %d\n",i);
}
// Output:
// ./program: This contains a variable: 1
where optv
counts the number of "-v" options found on the command line and prog
contains the program name (neither shown). This works well, but the problem is that I have to use a variable. V1("Output")
will generate a compiler error. I could always use V1("Output%s","")
but there should be a cleaner solution.
The GNU C preprocessor has a special feature that lets you delete the trailing comma when there are no arguments filling the variadic portion by prepending the token-pasting operator ##
to __VA_ARGS__
:
#define V1(str, ...) if(optv < 1); else printf("%s: "str,prog, ## __VA_ARGS__)
Alternatively, if you wish to remain fully C99 compliant, you could incorporate the the format string parameter into the ellipsis, but in this instance you'll also need to refactor your code since you want to include the extra prog
parameter between the format string and the varargs. Something like this might work:
#define V1(...) if(optv < 1); else myprintf(prog, __VA_ARGS__)
int myprintf(const char *prog, const char *fmt, ...)
{
// Print out the program name, then forward the rest onto printf
printf("%s: ", prog);
va_list ap;
va_start(ap, fmt);
int ret = vprintf(fmt, ap);
va_end(ap);
return ret;
}
Then, V1("Output")
expands to myprintf(prog, "Output")
without using any non-C99 compiler extensions.
EDIT
Also note that I inverted the if
condition in the macro, due to some weird issues that can arise if you invoke the macro inside an if
statement without braces—see this FAQ for a detailed explanation.