Defining define
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
#endifIt produces a compiler error:
test.cpp:3:18: error: expected value in expression
#if DEFINED_VALUESo to use #if, we need to have an actual value, like this.
#define DEFINED_VALUE 0test.cpp:6:2: warning: "#if DEFINED_VALUE" is not activeThen a non-zero value will “activate” the branch.
#define DEFINED_VALUE 1test.cpp:6:2: warning: "#if DEFINED_VALUE" is activeIt 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
#endiftest.cpp:5:2: warning: 1 and 1 is active
test.cpp:9:2: warning: 1 or 0 is activeNext 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
#endiftest.cpp:4:2: warning: "#ifdef DEFINED_VALUE" is activeSo just the presence of the defined value will activate this branch. We can comment it out to deactivate it.
//#define DEFINED_VALUEtest.cpp:6:2: warning: "#ifdef DEFINED_VALUE" is not activeWe 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
#endiftest.cpp:6:2: warning: "#ifndef DEFINED_VALUE" is not activeCan 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
#endiftest.cpp:4:12: warning: extra tokens at end of #ifdef directive
#ifdef ONE && ZERO
test.cpp:5:2: warning: 1 and 0 is activeNo, 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
#endiftest.cpp:4:2: warning: "#ifdef ZERO" is activeSo 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
#endiftest.cpp:4:2: warning: "#if defined(DEFINED_VALUE)" is activeIf the value is not defined, we get the other leg of the branch:
//#define DEFINED_VALUEtest.cpp:6:2: warning: "#if defined(DEFINED_VALUE)" is not activeWe 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
#endiftest.cpp:4:2: warning: "#if !defined(DEFINED_VALUE)" is activeIf 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
#endiftest.cpp:4:2: warning: "#if defined(DEFINED) && !defined(UNDEFINED)" is activeWhat about numeric values though?
#define ZERO 0
#if defined(ZERO)
#warning "#if defined(ZERO)" is active
#else
#warning "#if defined(ZERO)" is not active
#endiftest.cpp:4:2: warning: "#if defined(ZERO)" is activeThe behavior of #if defined is the same as the behavior of #ifdef in this respect.
Enjoy Reading This Article?
Here are some more articles you might like to read next: