0

I am trying to define a macro which includes a pre-processor if-statement that checks the DEBUG state in its body. Essentially, here is what I would like to achieve:

Option 1

#define MY_MACRO  { \
                    #ifdef _DEBUG \
                         MyFunction(); \
                    #endif \
                  }

I know that an alternative implementation is the following:

Option 2

#ifdef _DEBUG
   #define MY_MACRO  MyFunction();
#else
   #define MY_MACRO
#endif

So, I have two questions:

  1. Is Option 1 above, correctly implemented? If not, what is the right way to do it?
  2. Is Option 2 always the preferred way to do this?
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
hANI
  • 213
  • 3
  • 13

2 Answers2

1

Yes, option two is the way to do this. As you probably discovered, option 1 just doesn't work. You should probably remove the trailing ; in the substitution though:

#define MY_MACRO  MyFunction()

Otherwise, if someone writes:

if (condition)
    MY_MACRO;
else
    do_something_else();

The substitution yields:

if (condition)
    MyFunction();;
else
    do_something_else();

...and the two semicolons tell the compiler that an if statement terminated and was followed by an empty statement, then there's an unexpected and illegal else.

Depending on the exact situation, it may be better to have:

#define MY_MACRO()  MyFunction()

So the calling code looks like:

MY_MACRO();

That's more consistent with a function call.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Should probably use the `do { ... } while (0)` trick, see http://stackoverflow.com/questions/154136/do-while-and-if-else-statements-in-c-c-macros – amdn Mar 26 '14 at 06:37
  • @amdn: that's only useful for multi-line substitutions (and `while (false)` is better form ;-P). – Tony Delroy Mar 26 '14 at 06:48
  • Thanks for your response. I'd assume that without a ; in the macro, one could run into a similar problem if the macro is used without one as well. This way, it is consistent with usages such as Qt: Q_OBJECT – hANI Mar 26 '14 at 14:58
  • @hANI: IMHO anything that's generating a statement or statements - i.e. used in a function to request actual run-time processing - is a strong candidate for function-call like notation ala `#define F() xxx`, `#define F() do { ... } while (false)` or `#define F() if (...) { ... } else` (i.e. caller provides `;`). It's mainly macros that inject declarations, definitions, access specifiers etc. leave statement blocks or class/function definitions open (i.e. finish with '{') that *need* to avoid any semicolon. `Q_OBJECT` is such a macro - injecting a static data member & functions in a class. – Tony Delroy Mar 27 '14 at 01:14
1

There is no way to have a macro expand to any kind of preprocessor directive, so option 1 just won't work. The closest you can come is to define macro that has multiple definitions depending on ifdefs, as you've done in option 2. One thing you can do is define a macro that just expands to its arguments or to nothing, depending on ifdefs:

#ifdef _DEBUG
#define IF_DEBUG(...)    __VA_ARGS__
#else
#define IF_DEBUG(...)
#endif

Now you can use this macro in other macros:

#define MY_MACRO    IF_DEBUG( MyFunction() )
Chris Dodd
  • 119,907
  • 13
  • 134
  • 226