views:

366

answers:

8

From what I understand assert is a macro in C and supposedly if you use it at compile time but leave it disabled then there won't be overhead (which might not be correct I don't know). The problem for me is that what I'd like to do is get all the variables passed to my function and print out that output, but only if I want debugging enabled. Here is what I have so far:

int exampleFunction (int a, int b)
{
  #ifdef debugmode
  printf("a = %i, b = %i", a, b);
  #endif 
}

I'm wondering if there is any easier (and less ugly) method for doing something like this. xdebug for php has this feature and I've found is saves me an enormous amount of time when debugging so i want to do it for each function.

Thanks

A: 

Look at

bill
+11  A: 

try this:

#ifdef debugmode
#define DEBUG(cmd) cmd
#else
#define DEBUG(cmd)
#endif


DEBUG(printf("a = %i, b = %i", a, b));

now, if you have debugmode defined, you get your print statement. otherwise, it never shows up in the binary.

eduffy
Sadly you're left with a useless function call in its place but I +1 this in my struggle to be less of a purist.
Kai
+1 My choice as well
Tom
Hmm this left me with a compiler error of:`b' undeclared (first use this function) Not sure why
John Baker
@Kai - There is no useless function call when debugmode is undefined. The preprocessor replaces the printf with just a semicolon, that then gets translated to nothing in the executable.
eduffy
This should work with any C90 implementation, which puts it ahead of some of the solutions that only work with C99 functionality.
David Thornley
The non-debug version of the macro should ensure that the compiler validates the debug code. For example, the #else clause might be: #define DEBUG(cmd) do { if (0) cmd; } while (0) -- the compiler validates the command, but then optimizes it away (and if it doesn't optimize it away, you've got bigger problems than this - get a new compiler).
Jonathan Leffler
A: 

You can define PRINTF_IF_DEBUGGING as

#ifndef NDEBUG
#define PRINTF_IF_DEBUGGING(X) printf(X)
#else
#define PRINTF_IF_DEBUGGING(X)
#endif

This will centralize the #ifdefs in only one place.

florin
That won't work if printf needs more than 1 argument.
eduffy
Right. Unless you use variadic macros, the solution should be more like `#define FOO(X) printf X` to be used like `FOO(("%some", args));`
ephemient
+1  A: 
if (MY_DEBUG_DEFINE) {
        do_debug_stuff();
}

Any half decent compiler would optimize the block away. Note you need to define MY_DEBUG_DEFINE as a boolean (ie 0 or not 0).

#define MY_DEBUG_DEFINE defined(NDEBUG)

If you happen to compile with maximum warning level, this trick avoids unreferenced argument.

You can call me Chuck
+3  A: 

Using GCC, I really enjoy to add, per file:

#if 0
#define TRACE(pattern,args...)   fprintf(stderr,"%s:%s/%u" pattern "\n",__FILE__,__FUNCTION__,__LINE__,##args)
#else
#define TRACE(dummy,args...)
#endif

and then in the code:

i++;
TRACE("i=%d",i);

i will be printed only when I activate the TRACE() macro in the top of the file. Works really great, plus it prints the source file, line and function it occurred.

0x6adb015
A: 

Well, the problem with the PRINT_DEBUG type macros as given here, is that they only allow one parameter. For a proper printf() we'll need several, but C macros don't (presently) allow variable arguments.

So, to pull this off, we've got to get creative.

#ifdef debugmode
     #define PRINTF   printf
#else
     #define PRINTF    1 ? NULL : printf
#endif

Then when you write PRINTF("a = %i, b = %i", a, b);, in non-debug mode, it will be renders as (effectively):

 if (true) NULL;
 else printf("a = %i, b = %i", a, b);

The compiler is happy, but the printf is never execute, and if the compiler if bright (i.e, any modern C compiler), the code for the printf() will never be generated, as the compiler will recognize that path can never be taken.

Note, however, that the parameters will still be evaluated, so if they have any side effects (i.e, ++x or a function call), they code may be generated (but not executed)

James Curran
Gcc allows multi-args, see my answer on this question.
0x6adb015
I believe something like this is in C99.
David Thornley
I don't know why people are marking this down--- As far as I can see, it's the only answer which provides a) a Standard solution which b) requires neither a particular compiler nor a special syntax. It is EXACTLY what the OP asked for.
James Curran
+1  A: 

Workaround to get vararg with preprocessors that don't support it

#define DEBUG

#ifdef DEBUG
#define trace(args) printf args
#else
#define trace(args)
#endif


int dostuff(int value)
{


    trace(("%d", value));

}
Joakim Elofsson
A: 

I would also print some other C preprocessor flags that can help you track problems down

printf("%s:%d {a=%i, b=%i}\n", __FILE__, __LINE__, a, b);
Pete