Skip to main content

C++ Preprocessor Directives

C++ preprocessor visualized: macros, header guards, conditional compilation, and #include directives explained interactively.

The C++ Preprocessor

The preprocessor is your first line of code transformation, running before compilation begins. It handles macros, includes, and conditional compilation through simple text substitution.

C++ Preprocessor Visualizer

Inspect macro expansion, header inclusion and directives before the compiler parses the translation unit.

Preprocessing Pipeline

??=Trigraph ReplacementLegacy character replacement
\ Line SplicingJoin continued lines
[ ]TokenizationBreak into tokens
#Macro ExpansionReplace macros
<>Include ProcessingInsert header files
#ifConditional CompilationProcess conditionals

Inspecting the original source for simple macro.

Original Code · inspecting
#define PI 3.14159
#define SQUARE(x) ((x) * (x))

float area = PI * SQUARE(radius);
After Preprocessing
float area = 3.14159 * ((radius) * (radius));

Explanation: Macros are replaced with their definitions. Note the parentheses in SQUARE to ensure correct precedence.

Preprocessor Commands
g++ -E main.cpp -o main.i    # Preprocess only
g++ -dM -E main.cpp          # Show all defined macros
g++ -H main.cpp              # Show included headers
Authored preprocessing sketches omit header contents and compiler line markers. Trigraph replacement is a legacy phase removed from standard C++ in C++17.

Key Directives

Macros (#define)

C++
#define PI 3.14159
#define SQUARE(x) ((x) * (x))
#define MAX(a,b) ((a) > (b) ? (a) : (b))

Include Guards

C++
#ifndef HEADER_H
#define HEADER_H
// Header content
#endif

// Or modern:
#pragma once

Conditional Compilation

C++
#ifdef DEBUG
  #define LOG(x) std::cout << x
#else
  #define LOG(x)
#endif

Common Pitfalls

Macro Expansion Can Repeat Side Effects

  • Missing parentheses: #define DOUBLE(x) x * 2 → Use ((x) * 2)
  • Side effects: SQUARE(i++) expands to ((i++) * (i++))
  • Name collisions: Macros are global, use unique names

Best Practices

  1. Prefer const and constexpr over macros
  2. Use ALL_CAPS for macro names
  3. Always parenthesize macro parameters
  4. Document macro behavior
  5. Consider inline functions instead

Next Steps

If you found this explanation helpful, consider sharing it with others.

Mastodon