Public Group

# Variadic macros for debug purposes

This topic is 3709 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi guys, I was trying to write a variadic macro to be able to check some values as my game is running and I came across the following problem: I want a macro that will check an expression and, if it's false, print the expression that failed along with other info into a text file. I also wanted to allow for printing a custom message, if given. So I have an ASSERT(x, ...) macro which has the following line after all the info printing is done (where err_log is a proper FILE*): fprintf(err_log, "Msg: "__VA_ARGS__); This works as intended when the user does give it a message, but if he doesn't I get "C2660: 'fprintf': function does not take 1 arguments". Shouldn't __VA_ARGS__ amount to nothing if no other parameters are passed? So shouldn't I end up with printing just "Msg: " to the file? I would greatly appreciate it if someone could point out what I'm missing here. Another thing that might help me out: Is there a way, from within the macro, to check whether __VA_ARGS__ will expand to anything at all (i.e. if it's "empty")? If so, maybe I can just put an if/else in there to print nothing if a message wasn't given. A preemptive thanks,

##### Share on other sites
Try wrapping the fprintf in your own function that takes nothing but a variable argument list (and internally prepends the "Msg: " string). This should help you reduce dependencies and hide data too.

##### Share on other sites
The following
#include <cstdio>#define TEST(x,...) if((x)) { fprintf(stdout,"Msg: " __VA_ARGS__); }int main() {    TEST(true);    TEST(true,"PRINT\n");}

produces the expected results for me with VS2008. What's your actual code look like? The error is interesting -- it says you're trying to call fprintf() with one parameter. But you should have at least two, according do your examples. I think the problem lies in part of the code you have not shown us.

##### Share on other sites
Excellent point Josh,

Below is the file which will house the macros (hope formatting doesn't blow up):

//-----------------------------------------------------------------------
#ifndef DEBUG_TOOLS_H
#define DEBUG_TOOLS_H
//-----------------------------------------------------------------------

//files needed in the debug macros
#include <stdio.h> //printf(), fprintf()

//-----------------------------------------------------------------------

#ifdef DEBUG_MODE

#define ASSERT(x,...)
{
if(0 == (x))
{
FILE* err_log;
err_log = fopen("error_log.txt", "wt");
printf("assert!\n");
fprintf(err_log, "Failed expression: %s\nIn function: %s\nLine: %d\nIn file: %s\n", #x, __FUNCTION__, __LINE__, __FILE__);
printf(err_log, "\n");
fprintf(err_log, "Msg: "__VA_ARGS__);
fclose(err_log);
}
}
#else //#ifdef DEBUG_MODE. if DEBUG_MODE isn't defined the macros don't do anything
#define ASSERT(x)
#endif //#ifdef DEBUG_MODE

//------------------------------------------------------------------------
#endif //DEBUG_TOOLS_H

And my main is simply:

#include "debug_tools.h"

int main(void)
{
int y = 0;
ASSERT(y);
return 0;
}

which produces the following:

error C2143: syntax error : missing ')' before 'string', main.cpp, 6
error C2660: 'fprintf' : function does not take 1 arguments, main.cpp, 6
error C2059: syntax error : ')', main.cpp, Line:6

I am using Visual Studio 2005. Would that make a difference in the way macros are handled?

##### Share on other sites
Can you do this:

#define ASSERT(x,...)
{
if(0 == (x))

or shouldn't you have the \ line terminators for a multiline define?

##### Share on other sites
Sorry to have left those out. I do have them in the actual file but apparently I deleted them while trying to make the formatting work in html, and forgot to put them back in.

Edit: Josh, I tried copy/pasting your code exactly into my program and it still complains about calling fprintf with one argument. Could the problem be the compiler?

[Edited by - koralcem on April 22, 2008 11:09:35 PM]

##### Share on other sites
What compiler are you using? Its only relatively recently that these have compiled across the different platforms I use at work (VS was a relatively early adopter I think).

Does this compile as expected for you?:

static inline void Foo(...){}
#define ASSERT(x,...) do { Foo(__VA_ARGS__); } while(0)

//Tests (Compile in VS'08)
ASSERT(0, "bob");
ASSERT(0, "bob %s", "and sheila");
ASSERT(0);

##### Share on other sites
Quote:
 Edit: Josh, I tried copy/pasting your code exactly into my program and it still complains about calling fprintf with one argument. Could the problem be the compiler?

It may be. Your example worked when I copied it. 2005 may have different semantics for the operation of that macro expansion -- could be what's causing it to swallow one of the parameters.

##### Share on other sites
Yeah, I'm assuming it's just the compiler then. I'll just make 2 different macros, one for when the user wants to supply a message and one when not. Thanks a lot though, I really appreciate your guys' time.

• 38
• 12
• 10
• 10
• 9
• ### Forum Statistics

• Total Topics
631365
• Total Posts
2999585
×