When I encounter a preprocessor branch in code I usually find myself struggling to
recall the difference between #if, #ifdef, and #if defined. This post is an
attempt to provide myself with a quick reference. Hopefully it might help others as
well.
This chart summarizes things:
Checks for existence
Numeric defines
Supports && and ||
Supports !
#if
No
Yes
Yes
No
#ifdef
Yes
No
No
One condition (#ifndef)
#if defined
Yes
No
Yes
Many conditions (!defined())
The details are below.
Start with #if
Let’s start with this code:
It produces a compiler error:
So to use #if, we need to have an actual value, like this.
Then a non-zero value will “activate” the branch.
It is also possible to use #if for logical conditions like && and ||.
Next up: #ifdef
Now let’s try #ifdef.
So just the presence of the defined value will activate this branch. We can comment
it out to deactivate it.
We can use #ifndef to determine if a value is not defined.
Can we do Boolean operations, as with #if?
No, it seems Boolean conditions are not possible here. Even worse, we only get a
warning, and the condition is evaluated as if the #ifdef is true! In this case,
the actual behavior is the opposite of my intuition. This could be lost in a sea of
warnings, and end up being difficult to track down.
In addition, numeric values are only checked for existence.
So maybe surprisingly, the behavior of #ifdef ZERO and #if ZERO are opposite.
Last but not least: #if defined
Finally, we can use the defined keyword, which something like a function call.
If the value is not defined, we get the other leg of the branch:
We can also check for a value that is not defined.
If addition, this syntax supports Boolean operators (&&, ||, and !):
What about numeric values though?
The behavior of #if defined is the same as the behavior of #ifdef in this
respect.