Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

Conditional compilation is a mechanism of the C preprocessor that selectively includes or excludes segments of source code from the translation unit before the lexical analysis and parsing phases of the compiler. It relies on preprocessor directives to evaluate integer constant expressions or check macro definitions, determining exactly which blocks of code are passed to the compiler and which are discarded.

Core Directives

The preprocessor uses a specific set of directives to manage conditional blocks. Every conditional block must be terminated with an #endif directive.
  • #if: Evaluates an integer constant expression. If the expression evaluates to a non-zero value (true), the subsequent code block is included.
  • #ifdef: Checks if a specific macro identifier is currently defined.
  • #ifndef: Checks if a specific macro identifier is currently not defined.
  • #elif: Acts as an “else if”, evaluating a new constant expression if the preceding #if or #elif evaluated to zero.
  • #else: Provides a fallback block of code if all preceding conditions in the chain evaluated to zero.
  • #endif: Terminates the conditional compilation block.

Syntax Visualization

Expression-Based Evaluation:
#if constant_expression
    /* Code included if constant_expression evaluates to non-zero */
#elif another_constant_expression
    /* Code included if previous conditions are zero and this is non-zero */
#else
    /* Code included if all preceding conditions evaluate to zero */
#endif
Definition-Based Evaluation:
#ifdef MACRO_NAME
    /* Code included if MACRO_NAME is defined (regardless of its value) */
#endif

#ifndef MACRO_NAME
    /* Code included if MACRO_NAME is NOT defined */
#endif

The defined Operator

For more complex conditions, the preprocessor provides the defined unary operator. It yields 1 if the identifier is defined as a macro, and 0 otherwise. This operator allows developers to combine multiple definition checks using standard C logical operators (&&, ||, !) within a single #if or #elif directive.
#if defined(MACRO_A) && !defined(MACRO_B) || (VERSION >= 2)
    /* Code included based on compound boolean logic */
#endif
Note: #ifdef MACRO is strictly equivalent to #if defined(MACRO).

Evaluation Rules and Mechanics

When the preprocessor encounters an #if or #elif directive, it follows a strict sequence of evaluation:
  1. Macro Expansion: All macros within the controlling expression are expanded, except those that are operands to the defined operator.
  2. Identifier Replacement: Any remaining identifiers that have not been expanded into macros (excluding keywords like defined) are implicitly replaced with the integer constant 0.
  3. Expression Evaluation: The resulting expression is evaluated according to the rules of C integer arithmetic.
Constraints on Expressions:
  • The expression must resolve to an integer constant expression.
  • Floating-point constants, string literals, and cast operators are strictly prohibited and will result in a preprocessing error.
  • The preprocessor supports standard relational (<, <=, >, >=, ==, !=), logical (&&, ||, !), and bitwise (&, |, ^, <<, >>, ~) operators.
  • Because the evaluation happens before compilation, the sizeof operator cannot be used, as the preprocessor has no knowledge of target architecture data types or memory layouts.
Master C with Deep Grasping Methodology!Learn More