-3

I have the following code

#define LogError(...) fprintf(stderr, __VA_ARGS__)

And I want another macro to print to the error log only in debug mode, so I expect that, with

#define DebugLogError(...) \
    #ifndef NDEBUG \
    fprintf(stderr, __VA_ARGS__); \
    #endif

code DebugLogError("hello %s", "world") to expand to

    #ifndef NDEBUG 
    fprintf(stderr, "hello %s", "world") \
    #endif

But the code is not compiling. How can this be implemented?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278

1 Answers1

3

The C standard does not provide features for using preprocessor directives inside macros. Instead of trying use a #if inside a macro, use the #if to control how you define the macro:

#if defined NDEBUG
    // If NDBUG is defined, define the macro to be replaced by nothing.
    #define DebugLogError(...)
#else
    // Otherwise, define the macro to print a debugging message.
    #define DebugLogError(...) fprintf(stderr, __VA_ARGS__);
#endif

However, it is often preferable to modify the macro so it can be used like a function call followed by a ;, fitting more smoothly into the C grammar:

#if defined NDEBUG
    // If NDBUG is defined, define the macro to be replaced by nothing.
    #define DebugLogError(...) \
        do { } while (0)
#else
    // Otherwise, define the macro to print a debugging message.
    #define DebugLogError(...) \
        do fprintf(stderr, __VA_ARGS__); while (0)
#endif

Defining them in the latter form will avoid errors where an extra semicolon (in the no-NDEBUG case) or missing code (in the NDEBUG case) would cause problems, like:

if (SomeCondition)
    DebugLogError(stuff);
else
    OtherCode;
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312