b degnan
b degnan

Reputation: 692

"too many arguments for format" with macro

I have a debug macro that I use for quick and dirty outputs. I've been trying to determine how to make code compile clean on gcc 5.4. It doesn't give any issues on earlier version of gcc (4.x) or clang (11.0.3). The error is this:

main.c: In function ‘main’:
main.c:4:38: warning: too many arguments for format [-Wformat-extra-args]
         do { if (1){ fprintf(stdout, "debug:%s:%04d:%s: " fmt, __FILE__, \
                                      ^
main.c:10:2: note: in expansion of macro ‘DEBUGPRINT’
  DEBUGPRINT("How to have no arguments?\n", NULL);

The code that I've been using to try to determine how to fix this is:

#include <stdio.h>

#define DEBUGPRINT(fmt, ...) \
    do { if (1){ fprintf(stdout, "debug:%s:%04d:%s: " fmt, __FILE__, \
                            __LINE__, __func__, __VA_ARGS__);} } while (0)

int main(int argc, char *argv[])
{
    DEBUGPRINT("nums: %04i, %04i\n", 0x1234,0x5678);
    DEBUGPRINT("How to have no arguments?\n", NULL);
    return(0);
}   

As one can see, if I have arguments, there's not problem. It's only if I have a message that's does not have arguments. I guess that I could pass a "\n" with '%s', but I was just curious if there was a way to handle the NULL.

Upvotes: 2

Views: 961

Answers (2)

Luis Colorado
Luis Colorado

Reputation: 12668

In order to have no arguments, you can do the following:

#include <stdio.h>

/* SEPARATE THE COMMA FROM THE __VA_ARGS__ macro with
 * the ## token */
#define DEBUGPRINT(fmt, ...) \
    do { if (1){ fprintf(stdout, "debug:%s:%04d:%s: " fmt, __FILE__, \
                            __LINE__, __func__,## __VA_ARGS__);} } while (0)
/* THIS TOKEN ELIMINATES THE COMMA ------------^^  */

int main(int argc, char *argv[])
{
    DEBUGPRINT("nums: %04i, %04i\n", 0x1234,0x5678);
    DEBUGPRINT("How to have no arguments?\n");
    return(0);
}   

I'm afrid it is not included in the standard, but it is an extension shared by CLANG and GCC compilers.

This is the output on my system:

$ a.out
debug:pru3225.c:0012:main: nums: 4660, 22136
debug:pru3225.c:0013:main: How to have no arguments?
$ _

Upvotes: 1

dbush
dbush

Reputation: 223907

The fmt argument needs to be left out, and you'll need to split the fixed part of the printing from the arguments you pass in.

#include <stdio.h>

#define DEBUGPRINT(...) \
    do { printf("debug:%s:%04d:%s: ", __FILE__, __LINE__, __func__);\
         printf(__VA_ARGS__);\
    } while (0)

int main(int argc, char *argv[])
{
    DEBUGPRINT("nums: %04i, %04i\n", 0x1234,0x5678);
    DEBUGPRINT("How to have no arguments?\n");
    return(0);
}

Output:

debug:x1.c:0016:main: nums: 4660, 22136
debug:x1.c:0017:main: How to have no arguments?

Upvotes: 4

Related Questions