Skip to main content

Conditional Compilation — #ifdef

Conditional compilation directives let you include or exclude parts of the code before compilation, based on whether a macro is defined or a condition is true. This is useful for platform-specific code, debug builds, and feature flags.

#ifdef — If Defined

Compiles the block only if the macro has been defined:
#define DEBUG

#ifdef DEBUG
    printf("Debug mode ON\n");
#endif
If DEBUG is defined, the printf is compiled. If not, it’s completely removed.

#ifndef — If Not Defined

Compiles the block only if the macro has NOT been defined (most commonly used as include guards):
#ifndef MY_HEADER_H
#define MY_HEADER_H

// header content here

#endif

#if, #elif, #else, #endif

More powerful: evaluate a constant expression, not just whether a macro exists.
#define VERSION 2

#if VERSION == 1
    printf("Running version 1\n");
#elif VERSION == 2
    printf("Running version 2\n");
#else
    printf("Unknown version\n");
#endif

Complete Example: Debug vs Release Build

#include <stdio.h>

// Comment out the next line to build in release mode
#define DEBUG_MODE

int main() {
    int x = 42;

#ifdef DEBUG_MODE
    printf("[DEBUG] x = %d\n", x);
#endif

    printf("Program running.\n");
    return 0;
}
With DEBUG_MODE defined:
[DEBUG] x = 42
Program running.
Without DEBUG_MODE:
Program running.

Platform-Specific Code

#ifdef _WIN32
    printf("Running on Windows\n");
#elif defined(__linux__)
    printf("Running on Linux\n");
#elif defined(__APPLE__)
    printf("Running on macOS\n");
#endif

Summary of Conditional Directives

DirectiveMeaning
#ifdef NAMECompile if NAME is defined
#ifndef NAMECompile if NAME is NOT defined
#if exprCompile if expression is non-zero
#elif exprElse-if branch
#elseElse branch
#endifEnd of conditional block
#undef NAMEUndefine a macro