SyntaxStudy
Sign Up
C Conditional Compilation: #ifdef, #if, and #pragma
C Beginner 1 min read

Conditional Compilation: #ifdef, #if, and #pragma

Conditional compilation directives let you include or exclude sections of code based on whether macros are defined or what their values are. `#ifdef NAME` is true if `NAME` has been defined with `#define` (the value doesn't matter). `#ifndef NAME` is true if `NAME` has not been defined. `#if expr` evaluates a constant expression, enabling numeric comparisons like `#if VERSION >= 2`. These directives are closed with `#endif` and can have an `#else` or `#elif` branch. Conditional compilation is essential for writing portable code that targets multiple operating systems or architectures. Platform-specific blocks are guarded by macros defined by the compiler: `_WIN32` on Windows, `__linux__` on Linux, `__APPLE__` on macOS. Feature macros like `__cplusplus` allow header files to be safely shared between C and C++ translation units. Compile-time flags passed with `-D` on the GCC command line (e.g. `gcc -DDEBUG`) define macros without changing source files. `#pragma` directives pass implementation-specific instructions to the compiler. `#pragma once` for header guards is the most common. `#pragma pack(n)` controls struct member alignment, reducing padding at the cost of potentially unaligned accesses. `_Pragma("...")` is the C99 standard equivalent that can be used inside macros. Unrecognised `#pragma` directives are silently ignored by compilers that don't support them, making them safe to use.
Example
#include <stdio.h>

/* Platform detection */
#if defined(_WIN32) || defined(_WIN64)
    #define PLATFORM "Windows"
    #define PATH_SEP '\\'
#elif defined(__APPLE__)
    #define PLATFORM "macOS"
    #define PATH_SEP '/'
#elif defined(__linux__)
    #define PLATFORM "Linux"
    #define PATH_SEP '/'
#else
    #define PLATFORM "Unknown"
    #define PATH_SEP '/'
#endif

/* Build configuration */
#ifdef DEBUG
    #define LOG(fmt, ...) \
        fprintf(stderr, "[DEBUG %s:%d] " fmt "\n", \
                __FILE__, __LINE__, ##__VA_ARGS__)
#else
    #define LOG(fmt, ...)  /* no-op in release builds */
#endif

/* Version guard */
#define MY_VERSION 3
#if MY_VERSION < 2
    #error "Version 2 or higher is required"
#endif

/* C/C++ compatible header */
#ifdef __cplusplus
extern "C" {
#endif

void library_function(void);

#ifdef __cplusplus
}
#endif

void library_function(void)
{
    printf("library_function called on %s\n", PLATFORM);
}

int main(void)
{
    printf("Platform:   %s\n", PLATFORM);
    printf("Path sep:   '%c'\n", PATH_SEP);
    printf("Version:    %d\n", MY_VERSION);

    LOG("main started, version=%d", MY_VERSION);
    library_function();

    /* Compile with -DDEBUG to see LOG output */
    printf("Compile with -DDEBUG to enable debug logging.\n");
    return 0;
}

This is the last lesson in this section.

Create a free account to earn a certificate