Defining define
January 30, 2017
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:
#define DEFINED_VALUE
#if DEFINED_VALUE
#warning "#if DEFINED_VALUE" is active
#else
#warning "#if DEFINED_VALUE" is not active
#endif
It produces a compiler error:
test.cpp:3:18: error: expected value in expression
#if DEFINED_VALUE
So to use #if
, we need to have an actual value, like this.
#define DEFINED_VALUE 0
test.cpp:6:2: warning: "#if DEFINED_VALUE" is not active
Then a non-zero value will “activate” the branch.
#define DEFINED_VALUE 1
test.cpp:6:2: warning: "#if DEFINED_VALUE" is active
It is also possible to use #if
for logical conditions like &&
and ||
.
#define ZERO 0
#define ONE 1
#if ONE && ONE
#warning 1 and 1 is active
#endif
#if ONE || ZERO
#warning 1 or 0 is active
#endif
test.cpp:5:2: warning: 1 and 1 is active
test.cpp:9:2: warning: 1 or 0 is active
Next up: #ifdef
Now let’s try #ifdef
.
#define DEFINED_VALUE
#ifdef DEFINED_VALUE
#warning "#ifdef DEFINED_VALUE" is active
#else
#warning "#ifdef DEFINED_VALUE" is not active
#endif
test.cpp:4:2: warning: "#ifdef DEFINED_VALUE" is active
So just the presence of the defined value will activate this branch. We can comment it out to deactivate it.
//#define DEFINED_VALUE
test.cpp:6:2: warning: "#ifdef DEFINED_VALUE" is not active
We can use #ifndef
to determine if a value is not defined.
#define DEFINED_VALUE
#ifndef DEFINED_VALUE
#warning "#ifndef DEFINED_VALUE" is active
#else
#warning "#ifndef DEFINED_VALUE" is not active
#endif
test.cpp:6:2: warning: "#ifndef DEFINED_VALUE" is not active
Can we do Boolean operations, as with #if
?
#define ZERO 0
#define ONE 1
#ifdef ONE && ZERO
#warning 1 and 0 is active
#else
#warning 1 and 0 is not active
#endif
test.cpp:4:12: warning: extra tokens at end of #ifdef directive
#ifdef ONE && ZERO
test.cpp:5:2: warning: 1 and 0 is active
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.
#define ZERO 0
#ifdef ZERO
#warning "#ifdef ZERO" is active
#else
#warning "#ifdef ZERO" is not active
#endif
test.cpp:4:2: warning: "#ifdef ZERO" is active
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.
#define DEFINED_VALUE
#if defined(DEFINED_VALUE)
#warning "#if defined(DEFINED_VALUE)" is active
#else
#warning "#if defined(DEFINED_VALUE)" is not active
#endif
test.cpp:4:2: warning: "#if defined(DEFINED_VALUE)" is active
If the value is not defined, we get the other leg of the branch:
//#define DEFINED_VALUE
test.cpp:6:2: warning: "#if defined(DEFINED_VALUE)" is not active
We can also check for a value that is not defined.
//#define DEFINED_VALUE
#if !defined(DEFINED_VALUE)
#warning "#if !defined(DEFINED_VALUE)" is active
#else
#warning "#if !defined(DEFINED_VALUE)" is not active
#endif
test.cpp:4:2: warning: "#if !defined(DEFINED_VALUE)" is active
If addition, this syntax supports Boolean operators (&&
, ||
, and !
):
#define DEFINED
#if defined(DEFINED) && !defined(UNDEFINED)
#warning "#if defined(DEFINED) && !defined(UNDEFINED)" is active
#else
#warning "#if defined(DEFINED) && !defined(UNDEFINED)" is active
#endif
test.cpp:4:2: warning: "#if defined(DEFINED) && !defined(UNDEFINED)" is active
What about numeric values though?
#define ZERO 0
#if defined(ZERO)
#warning "#if defined(ZERO)" is active
#else
#warning "#if defined(ZERO)" is not active
#endif
test.cpp:4:2: warning: "#if defined(ZERO)" is active
The behavior of #if defined
is the same as the behavior of #ifdef
in this
respect.