0

I have a question. In one of my projects i am using the FLAG PRINT to enable/disable the debug printfs. currently I am using something like this.

#ifdef PRINT
    printf("DEBUG");
#endif 

It is a pain to put this #ifdef before every printf. So I was thinking to 've a #define for the #ifdef, something like

#define DEBUG_PRINT 
#define PRINT (#ifdef DEBUG_PRINT)
#define ENDPRINT #endif

so that I can use like

PRINT
   printf("DEBUG");
ENDPRINT

but it is giving a compiler error. Can you tell me someway to simplify.

Thanks,

user1667630
  • 297
  • 6
  • 15

3 Answers3

2

A standard way is

#ifdef DEBUG_PRINT
#  define is_debug() (1)
#else
#  define is_debug() (0)
#endif

#define pr_dbg(fmt, ...) do { \
        if (is_debug()) \
            printf(fmt, __VA_ARGS__); \
    } while (0)

When using gcc, you can/should write

            printf(fmt, ## __VA_ARGS__);

to deal with empty args.

In your code you can write then

pr_dbg("foo=%u\n", foo);

Optimizer will throw away the expression when DEBUG_PRINT is not defined but your debug statements will be still checked for syntax errors. This avoids silent breakage when e.g. undefined variables are used within an #ifdef clause.

ensc
  • 6,704
  • 14
  • 22
1

How about a header with

#ifdef DEBUG
#define ON_DEBUG(X,...) do { X, __VA_ARGS__; } while( false )
#else
#define ON_DEBUG(X,...) do {} while( false )
#endif

and in your code, you simply use

ON_DEBUG( printf("Hallo, %s", "Welt") );

(the do-while forces you to add the final semicolon and protects the statement's in cases if (nested) if-statements, see Aaron McDaid's comment)

Daniel Frey
  • 55,810
  • 13
  • 122
  • 180
  • That could behave in a very weird way sometimes. Consider `if (x) ON_DEBUG( printf("hello"); printf("world"); ) else something();`. This `if` would pick up only the first printf. Instead you should do `#define ON_DEBUG(X,...) do { X,__VA_ARGS__ }while(0)` – Aaron McDaid Nov 14 '13 at 21:52
0

I would actually do it a different way entirely. First define the flag that turns printing on or off:

// uncomment to turn off debug printing
#define DEBUG_PRINT 1

Then conditionally define your printer macro depending of the definition state of DEBUG_PRINT:

#ifdef DEBUG_PRINT
#define PRINT (X) (printf(x))
#else
#define PRINT (x)
#endif

Which can be used simply as:

PRINT("foo");

But in reality, I wouldn't do any of this stuff at all. Instead, I'd have the turn-on/turn-off flag as above, and then build a class that does the printing:

// comment out to not do debug printing
//#define DEBUG_PRINTING 1

#ifdef DEBUG_PRINTING
class Printer
{
public:
    Printer() {}
    ~Printer()
    {
        std::cout << mOutput.str() << "\n";
    }

    template <typename TYPE> Printer& operator<< (const TYPE& val)
    {
        mOutput << val;
        return * this;
    }
    template <size_t N> Printer& operator<<  (const char(&ary)[N])
    {
        mOutput << ary;
        return * this;
    }
private:
    std::stringstream mOutput;
};
#else
class Printer
{
public:
    Printer() {};
    template <typename TYPE> Printer& operator<< (const TYPE& val)
    {
        return * this;
    }
    template <size_t N> Printer& operator<< (const char(&ary)[N])
    {
        return * this;
    }
};
#endif

int main()
{
    Printer() << "My output here. " << 42;
}

In optimized builds where the flag is not defined, most (if not all) of the code will be optimized away.

John Dibling
  • 99,718
  • 31
  • 186
  • 324