tags:

views:

545

answers:

9

Hi, I'm trying to do a debug system but it seems not to work.

What I wanted to accomplish is something like this:

#ifndef DEBUG
    #define printd //
#else
    #define printd printf
#endif

Is there a way to do that? I have lots of debug messages and I won't like to do:

if (DEBUG)
    printf(...)

code

if (DEBUG)
    printf(...)

...

EDIT: I chose AndreyT's answer as it is the direct answer to my question, regarding what I'm doing instead of #defining a comment is explained by Tim's and Xeor's answers.

A: 

If you're trying to debug something, it's time to get out of the "I'll just use lots of printf()/System.out.println()/alert()" mentality and use a real debugger.

To debug C, use GDB.

Matt Ball
The question was related to C .... You know, that language that is not C++?
Tim Post
Not always the best answer. There's times when printing trace logs in a specific format and then processing that with shell utilities can be faster/easier. [Though it should be a case of knowing what the debugger can do and consciously choosing an alternative.]
Ian G
More logging in debug builds is not a bad thing.
Yuliy
I think that that is possibly one of the worst pieces of advice I have ever read.
Dipstick
Matt Ball
@Bears: Your comment included System.out.println, which is no C (Also, not C++), I think that that's what TinkerTim was seeing... In general, it's important to be able to do both printf and debugger debugging. Using a debugger to debug UI code where you want to see what happens when the user clicks three things, can be difficult or impossible.
Brian Postow
System.out.println is Java and alert is Javascript. I was using those to refer to the "debugger-free" method of "debugging" programs written in those various languages. I thought those would be pretty recognizable, but I guess not.
Matt Ball
@chrisharris: I have seen much worse advice before. Ben doesn't really specify what he is doing, so i think it is fair to assume that debugging might be more convenient than putting printfs into the code.
Lucas
+7  A: 

You can put all your debug call in a function, let call it printf_debug and put the DEBUG inside this function. The compiler will optimize the empty function.

slurdge
Thank you, sanity at last .. except its mostly the work of the preprocessor.
Tim Post
In this case you could just call your function printd
tadman
That does not not disable the evaluation of arguments and does not disable the requirement for the arguments to be valid (like, declared, for example). In other words, it doesn't do what was requested.
AndreyT
@AndreyT, if any kind of link time optimization is done, the compiler will inline empty functions and remove dead code for evaluating arguments.
Jay Conrod
The problem is that it simply will not compile if the arguments are not valid in release context. It won't get to "optimization".
AndreyT
+5  A: 

No, you can't. Comments are removed from the code before any processing of preprocessor directives begin. For this reason you can't include comment into a macro.

Also, any attempts to "form" a comment later by using any macro trickery are not guaranteed to work. The compiler is not required to recognize "late" comments as comments.

The best way to implement what you want is to use macros with variable arguments in C99 (or, maybe, using the compiler extensions).

AndreyT
+1  A: 

The standard way is to use

#ifndef DEBUG
    #define printd(fmt, ...)  do { } while(0)
#else
    #define printd(fmt, ...) printf(fmt, __VA_ARGS__)
#endif

That way, when you add a semi-colon on the end, it does what you want. As there is no operation the compiler will compile out the "do...while"

Dipstick
Uh, no. That code won’t work at all.
Konrad Rudolph
with braces it would work
Samuel_xL
+9  A: 

С99 way:

#ifdef DEBUG
    #define printd(...) printf(__VA_ARGS__)
#else
    #define printd(...)
#endif

Well, this one doesn't require C99 but assumes compiler has optimization turned on for release version:

#ifdef DEBUG
    #define printd printf
#else
    #define printd if (1) {} else printf
#endif
Xeor
Correct, but not quite portable.
Tim Post
Added portable way :)
Xeor
Much better, but again the "portable" version does not disable the validity checks on the arguments. The proper way to do it in non-C99 implementation is given in Tim's answer.
AndreyT
And that's its good side I think. Why disable validity check on code that will be real in debug versions?
Xeor
Simple: because that code might be invalid in release versions. There's nothing wrong with debug code being invalid in release. Moreover, that's the way it is most of the time.
AndreyT
@AndreyT: Even though this question is quite old and has already been answered I'm intrigued with your comment. Could you provide or point to an example where debug code might be invalid in release versions? Thank you very much.
Carla Álvarez
A: 

As noted by McKay, you will run into problems if you simply try to replace printd with //. Instead, you could use variadric macros to replace printd with a function that does nothing as in the following.

#ifndef DEBUG
    #define printd(...) do_nothing()
#else
    #define printd(...) printf(__VA_ARGS__)
#endif

void do_nothing() { ; }

Using a debugger like GDB might help too, but sometimes a quick printf is enough.

Swiss
+10  A: 

A common trick is to do this:

#ifdef DEBUG
  #define OUTPUT(x) printf x
#else
  #define OUTPUT(x)
#endif

#include <stdio.h>
int main(void)
{   
  OUTPUT(("%s line %i\n", __FILE__, __LINE__));

  return 0;
}

This way you have the whole power of printf() available to you, but you have to put up with the double brackets to make the macro work.

The point of the double brackets is this: you need one set to indicate that it's a macro call, but you can't have an indeterminate number of arguments in a macro in C89. However, by putting the arguments in their own set of brackets they get interpreted as a single argument. When the macro is expanded when DEBUG is defined, the replacement text is the word printf followed by the singl argument, which is actually several items in brackets. The brackets then get interpreted as the brackets needed in the printf function call, so it all works out.

Tim
why not use printf(x) in the 1st macro ? wouldn't work ?
Samuel_xL
Good question. Now explained in the answer text.
Tim
also, you could use OUTPUT(x...) printf(x) to avoid double ().
Brian Postow
@Brian This wouldn't work if you wanted variable numbers of arguments. See explanatory text for details.
Tim
A: 

I use this construct a lot:

#define DEBUG 1
#if DEBUG
#if PROG1
#define DEBUGSTR(msg...)     { printf("P1: "); printf( msg); }
#else
#define DEBUGSTR(msg...)     { printf("P2: "); printf( msg); }
#endif
#else
#define DEBUGSTR(msg...)    ((void) 0)
#endif

This way I can tell in my console which program is giving which error message... also, I can search easily for my error messages...

Personally, I don't like #defining just part of an expression...

Brian Postow
A: 

It's been done. I don't recommend it. No time to test but the mechanism is kind of like this:

 #define printd_CAT(x) x ## x
 #ifndef DEBUG
    #define printd printd_CAT(/)
 #else
    #define printd printf
 #endif

This works if your compiler processes // comments in the compiler itself (there's no guarantee like the ANSI guarantee that there are two passes for /* comments).

Joshua