Ivan Lo Greco
Ivan Lo Greco

Reputation: 325

What am I doing wrong with this variadic macro in C?

I'm working on a university project and I made a macro wrapper of printf which can color the text, print the file, function and line of the instruction with a string error based on errno.

#define PRINT_WITH_COLOR(color, title, message, errno_code) printf(color "[" title "] " message " %s::%s:%d [%s]\n" RESET_COLOR_CONSOLE, __VA_ARGS__, __FILE__, __func__, __LINE__, strerror(errno_code));

This initially was divided in multiple printf but due to multithreading, the problem I'm facing is that when I have no argument to pass the comma remains there and the program doesn't compile. For that reason I used the ## to remove commas around my variadic parameter:

#define PRINT_WITH_COLOR(color, title, message, errno_code) printf(color "[" title "] " message " %s::%s:%d [%s]\n" RESET_COLOR_CONSOLE, ## __VA_ARGS__, __FILE__, __func__, __LINE__, strerror(errno_code));

I thought it was working because I didn't receive any error on my VS Code but the gcc compiler gives me this error pointing on the right comma next to the __VA_ARGS__ , <----:

expected expression before ‘,’ token

Edit Here is an example usage: I use it indirectly by calling this macro

#define PRINT_WARNING(err_code, message, ...) PRINT_WITH_COLOR(YELLOW_COLOR, "Warning", message, __VA_ARGS__)

And in my code I use it like that

PRINT_WARNING(EINVAL, "File %s cannot be written!", pathname);

The output is a yellow message in console [Warning] File foo cannot be written! filepath::func:line [errno msg]

Upvotes: 1

Views: 365

Answers (1)

Cheatah
Cheatah

Reputation: 1835

It is actually the macro expansion of PRINT_WARNING that eventually results in the problem, and you should use ## there too. I think you also wanted to pass the err_code as well:

#define PRINT_WARNING(err_code, message, ...) \
        PRINT_WITH_COLOR(YELLOW_COLOR, "Warning", message, err_code, ##__VA_ARGS__)

And the PRINT_WITH_COLOR macro should also end in , ...)

#define PRINT_WITH_COLOR(color, title, message, errno_code, ...) \
        printf(color "[" title "] " message " %s::%s:%d [%s]\n" RESET_COLOR_CONSOLE, \
               ##__VA_ARGS__, __FILE__, __func__, __LINE__, strerror(errno_code));

Upvotes: 2

Related Questions