#ifdef vs #if and if

Compile-time settings and whatnot often make use of #define#ifdef, and #if. I would like to make the case that using none of these is the best option, and plain old if-statements ought to be used most of the time.

Here’s a typical example:

Some debug code runs inside of a paged allocator to try and detect and report double free. This code can be quite slow, so we only want it to run in debug mode.

How would the use of an if statement be better in this situation compared to #ifdef DEBUG? The problem is that the DEBUG define is assumed to only exist in debug builds. Once the DEBUG define is run through the preprocessor it usually just disappears, as it’s often defined as nothing. Code can not always safely assume the define exists, and the #syntax must be used.

If instead we redefine DEBUG like so:

Any code can use integer literals as apart of any code. This includes if statements, function calls, templates, or what have you. We can re-write the first example to:

Compilers will strip away the first if statement resulting in the same run-time code as the first example. The else keyword can also be used after this if statement. If in the future, for any reason, it becomes a necessity to turn debug features on or off at run-time the DEBUG macro can be swapped out for some kind of global watch variable — suddenly the DEBUG macro becomes more immune to code maturation. An example:

Since the macro becomes a literal a mixture of both compile-time and run-time checks can be used freely as desired. An if statement can check the compile-time literal, and also check for run-time pointers at the same time. No #ifdef necessary. The #ifdef takes up an entire line in the source file, and is often (in some code editors) automatically shifted all the way to the left of the text file. These quirks can be avoided by not using #ifdef at all.

Here’s an example of single line for each #directive, vs using plain C code:

In the above example the difference in indentation can be visually jarring, and it’s fairly annoying to re-type the same thing multiple times in multiple places. Instead we can do something more like:

Using a literal can also play a bit nicer with MSVC’s intellisense. This can be useful for inspecting compile-time constants and debugging in general.

TwitterRedditFacebookShare

8 thoughts on “#ifdef vs #if and if

  1. Frank Gennari

    Not all compilers will optimize out the code inside the if() statement when a variable is used. Maybe all modern C/C++ compilers will, but the ATI and Nvidia GLSL shader compilers won’t. At least they won’t in all cases. I’ve written code that was slower to execute when using constant variables rather than #ifdefs, presumably because that extra code used more registers and memory on the GPU kernel. I would love it if the graphics driver vendors could fix these sorts of problems. It doesn’t seem like it should be that hard to determine which blocks of code are unreachable by doing some sort of static code analysis and constant propagation.

    Reply
    1. Randy Gaul Post author

      Oh good point. I sort of assumed C/C++ in the post and don’t really have opinions on GLSL. Thanks for sharing :)

      Reply
  2. Arthur Langereis

    Was this line a trick to see if someone would spot it or a legitimate mistake?

    This expression will always be true, provided you have not done unholy things with operator overloads.

    Reply
    1. Randy Gaul Post author

      Whoops, I think it should be &&. No trick, just typing things out on-the-spot without double checking carefully.

      Reply
  3. Arthur Langereis

    Sorry to keep giving you a hard time but…

    will always evaluate to false ;)

    I assume you wanted to check for ptr being between page->memory and the address of the next page of memory?

    Writing code in a blog post is only marginally simpler than doing those horrible whiteboard coding tests.

    BTW, I know I’ve strayed far from the intent of the post which I totally agree with. I’ve seen plenty of code that out of paranoia or fear of what the compiler might do will resort to macros or other “tricks” that in modern compilers are simply not necessary and makes things needlessly unreadable. I employ a “trust, but verify” attitude towards compilers, it’s usually fine, but in critical code I check the assembly as well :)

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *