Skip to main content

C Preprocessor Directives (#include, #define, Macros)

2 min read
Share:
On this page (10sections)

Introduction

The C preprocessor runs before compilation. It handles #include, #define, macro expansion and conditional compilation. Every .c file you write already uses the preprocessor when you write #include <stdio.h>.

Common Directives

DirectivePurpose
#includeInsert header file contents
#defineCreate macros and constants
#undefRemove a macro
#ifdef / #ifndef / #endifConditional compilation
#if / #elif / #elseNumeric/string conditions

#include

#include <stdio.h>   /* system header — search standard paths */
#include "mylib.h"   /* local header — search current directory first */

#define Constants and Macros

#define PI 3.14159
#define MAX(a, b) ((a) > (b) ? (a) : (b))

int main(void) {
    printf("PI = %f\n", PI);
    printf("MAX(4, 9) = %d\n", MAX(4, 9));
    return 0;
}

Sample Output

PI = 3.141592
MAX(4, 9) = 9

Function-like Macros — Parentheses Matter

Always parenthesize macro parameters to avoid operator-precedence bugs:

#define SQUARE(x) ((x) * (x))   /* correct */
/* #define SQUARE(x) x * x      wrong for SQUARE(1 + 2) */

Conditional Compilation

#define DEBUG 1

#if DEBUG
    #define LOG(msg) printf("DEBUG: %s\n", msg)
#else
    #define LOG(msg)
#endif

Best Practices

  • Prefer const variables over #define for typed constants when debugging matters.
  • Keep macros short; use inline functions (C99+) for complex logic.
  • Never put statements with side effects inside macro arguments unless you understand expansion rules.
  • Use include guards in headers: #ifndef MY_HEADER_H / #define MY_HEADER_H / #endif.

Common Mistakes

  • Forgetting parentheses in macro definitions.
  • Using #define for long multi-line logic — hard to debug.
  • Including the same header repeatedly without guards (duplicate symbol errors).

Continue learning with these related tutorials and programs:

Related Tutorials

Search tutorials