0

I have a bunch of preprocessor config options defined in config.h. I use them like so:

#if CONFIG_OPTION1
    /* do some stuff */
#endif

config.h contains their defines:

#define CONFIG_OPTION1 _DEBUG
#define CONFIG_OPTION2 _DEBUG || (NDEBUG && _WIN64)
...

The above doesn't work. I want to turn on and off these config options based on configuration (debug, release, etc) and/or other defines. It also doesn't work if I do:

#define CONFIG_OPTION1 defined(_DEBUG) || defined(NDEBUG)

I never get inside the #if CONFIG_OPTION1 even when the condition looks like it should be met. When I write #if defined(_DEBUG) that works fine, but #if with a macro as the condition fails. How can I fix this?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
David
  • 27,652
  • 18
  • 89
  • 138

1 Answers1

2

Well, as you've already noticed, you can't do it like that. Do something like this instead:

#if _DEBUG || (NDEBUG && _WIN64)
#   define CONFIG_OPTION2 1
#endif
Cat Plus Plus
  • 125,936
  • 27
  • 200
  • 224
  • 1
    +1. According to http://gcc.gnu.org/onlinedocs/cpp/Defined.html, "If the `defined` operator appears as a result of a macro expansion, the C standard says the behavior is undefined." – ruakh Jan 04 '12 at 21:09
  • @CatPlusPlus If I do this do I also need to `#define` it to `0` somewhere, like in a `#else`? – David Jan 04 '12 at 21:11
  • 1
    @Dave: You don't have to, no. An undefined macro-name is interpreted as zero automatically. – ruakh Jan 04 '12 at 21:14
  • @ruakh: Relying on undefined macros being zero is a very bad practice. It's better to explicitly define the macro to 0 and 1, and configure your compiler to issue an error whenever an undefined preprocessor symbol is used, that way you will find basic errors like spelling mistakes, and using symbols without including the proper header file etc. – Lindydancer Jan 04 '12 at 21:35
  • 1
    @Lindydancer: Interesting. What you say makes sense, but the GNU C Preprocessor doc that I linked to above actually suggests the exact opposite, saying that e.g. `#if defined BUFSIZE && BUFSIZE >= 1024` can be "simplified" to `#if BUFSIZE >= 1024` because of this property. – ruakh Jan 04 '12 at 22:31
  • @Lindydancer: It's completely standard behavior, and we've got 30 years of C and C++ code that assumes so. If you'd turn on such warnings (presuming they exist in the first place), you'd get tons of warnings even on reasonable code bases. – MSalters Jan 05 '12 at 12:34
  • @MSalters: You can do it -- we did in a very++ large code base, and found a substantial number of problems, and it prevents us from introducing new ones. (You, however, beats me when it comes to experience, I've only been programming C for about 25 years. On the other hand -- the last fifteen years I've been developing C compilers professionally. ;) Btw, if you are using VisualStudio the warning is 4668, for GCC it's -Wundef, and for IAR it's Pe193. – Lindydancer Jan 05 '12 at 12:46
  • @Lindydancer: Well, I wasn't personally around for all of those years (only 27; 20 of those professionally). The point is, I generally end up using code from others. E.g. `` which will generate C4668 warnings in MSVC (http://stackoverflow.com/questions/4001736/what-with-the-thousands-of-warnings-in-standard-headers-in-msvc-wall) – MSalters Jan 05 '12 at 13:43
  • @MSalters: Yes, we ran into similar problems... We solved it by including the "broken" headers first and then enabling the warning, that way we would see potential problems in our own code. – Lindydancer Jan 05 '12 at 14:00