I have some debugging code that looks like the following:
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define AT __FILE__ ":" TOSTRING(__LINE__)
void __my_error(const char*loc, const char *fmt, ...);
#define my_error(fmt, ...) __my_error(AT, fmt, ##__VA_ARGS__)
The last macro is used so I can insert the location into the debug output as to where the error occurred. However, when I call the function like this:
my_error("Uh oh!");
I would like my code to be C99, so I find when this compiles, I get the following error:
error: ISO C99 requires rest arguments to be used
I know I can solve this by changing the call to
my_error("Uh oh!", NULL);
But is there any way to make this look less ugly? Thanks!
macro expansion possible specifying __VA_ARGS__ The '...' in the parameter list represents the variadic data when the macro is invoked and the __VA_ARGS__ in the expansion represents the variadic data in the expansion of the macro. Variadic data is of the form of 1 or more preprocessor tokens separated by commas.
__VA_OPT__ is a new feature of variadic macros in C++20. It lets you optionally insert tokens depending on if a variadic macro is invoked with additional arguments. An example usage is comma elision in a standardized manner.
Variadic functions are functions that can take a variable number of arguments. In C programming, a variadic function adds flexibility to the program. It takes one fixed argument and then any number of arguments can be passed.
Preprocessor: __VA_ARGS__ : count arguments This is an attempt to define a few variadic macros that can be used to count the number of arguments given.
I see two solutions to this problem. (Three if you count 'stick with gcc').
Add a new macro for when you want to print a fixed string.
#define my_errorf(str) my_error(str, NULL)
Pro: Minimum amount of extra code.
Con: It's easy to use the wrong macro (but at least you notice this at compile time).
fmt
inside the '...'Vararg macro's can have only __VA_ARGS__ as parameter (unlike vararg functions). So you can put the fmt
argument inside the __VA_ARGS__ and change your function.
void __my_error(const char *loc, ...);
#define my_error(...) __my_error(AT, __VA_ARGS__)
Pro: One syntax/macro for all error messages.
Con: Requires rewriting of your __my_error
function, which might not be possible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With