views:

60

answers:

1

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!

+1  A: 

I see two solutions to this problem. (Three if you count 'stick with gcc').

Extra special case macro

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).

Put 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(...) __proxy_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.


Side note: Are __my_error and __proxy_error the same functions? In both cases I recommend choosing another name: All identifiers starting with two underscores (and most with a single) are reserved.

schot
Yes, the two functions are the same (typo on my part). I'll give solution number 2 a try and see if I can sort that out.What do you suggest for naming conventions for things which are essentially private (such as the `__my_error` function, which should never be called directly)?
Michael Mior
@Michael Let me know how it works out. I usually add a '_suffix' to the macro name like `my_error_real`, `my_error_private` or just `my_error_x` (from 'eXpanded').
schot
Solution number 2 seems to be working great :) Thanks!
Michael Mior