Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Conditional compilation

#if, #elseif, #else and #endif choose which lines are compiled at all. A line in a branch that is not taken is never compiled, so it costs nothing in the program and may even name things that do not exist.

'' Conditional compilation chooses which lines are compiled at all.
#define LOG_LEVEL 2
#define WITH_COLOUR

#if LOG_LEVEL >= 3
    print "logging: everything"
#elseif LOG_LEVEL = 2
    print "logging: warnings and errors"
#else
    print "logging: errors only"
#endif

'' #ifdef and #ifndef ask only whether a name is defined.
#ifdef WITH_COLOUR
    print "colour: on"
#endif
#ifndef WITH_SOUND
    print "sound: not built in"
#endif

'' defined( ) does the same inside an #if, and combines with andalso,
'' orelse and not.
#if defined( WITH_COLOUR ) andalso not defined( WITH_SOUND )
    print "a quiet, colourful build"
#endif

'' A line in a branch not taken is never compiled, so it may name
'' things that do not exist.
#if 0
    NoSuchProcedure( )
#endif
print "done"

Output

logging: warnings and errors
colour: on
sound: not built in
a quiet, colourful build
done
DirectiveKeeps the lines that follow when
#if exprthe constant expression is not zero
#elseif exprno earlier branch was taken and expr is not zero
#elseno earlier branch was taken
#ifdef NAMENAME is defined
#ifndef NAMENAME is not defined
defined( NAME )inside #if: true when NAME is defined

The expressions are worked out by the preprocessor, so they may use only constants and defined names. #if 0 … #endif is a quick way to switch off a block of code without commenting out every line.

Pitfall

#ifdef asks whether a name is defined, not what it is.

'' TRACE is 0 to turn tracing off -- or so the author thought.
#define TRACE 0

#ifdef TRACE
    print "#ifdef TRACE: tracing is on"
#endif

#if TRACE
    print "#if TRACE: tracing is on"
#else
    print "#if TRACE: tracing is off"
#endif
#ifdef TRACE: tracing is on
#if TRACE: tracing is off

TRACE is defined, as 0, so every #ifdef TRACE is true. Choose one convention per switch: either it is defined or not, and you test it with #ifdef, or it always has a value, and you test it with #if.

Activities

  1. Set LOG_LEVEL to 3, then to 1, and predict each output first.
  2. Define WITH_SOUND and see which two lines change.