C Preprocessor Directives
What is the Preprocessor?
The C preprocessor runs before compilation. It processes lines starting with # (called directives) and performs text substitution, file inclusion, and conditional compilation. The preprocessor output is pure C code that the compiler then compiles.
Common Preprocessor Directives
| Directive | Description |
|---|---|
#include | Include a header file |
#define | Define a macro (constant or function-like) |
#undef | Undefine a macro |
#ifdef | Compile if macro is defined |
#ifndef | Compile if macro is NOT defined |
#if / #elif / #else / #endif | Conditional compilation |
#pragma | Compiler-specific instructions |
#error | Emit a compile-time error message |
Predefined Macros
| Macro | Description | Example Value |
|---|---|---|
__FILE__ | Current source file name | "main.c" |
__LINE__ | Current line number | 42 |
__DATE__ | Compilation date | "Jan 15 2025" |
__TIME__ | Compilation time | "10:30:00" |
__STDC__ | 1 if standard C compiler | 1 |
#include <stdio.h>
// Object-like macros (constants)
#define PI 3.14159265
#define MAX_SIZE 100
#define NEWLINE '\n'
// Function-like macros (no type checking — use with care)
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define ABS(x) ((x) < 0 ? -(x) : (x))
// Multi-line macro using backslash
#define PRINT_INFO(name, val) \
printf("%-15s = %d\n", name, val)
int main() {
printf("PI = %.5f\n", PI);
printf("MAX_SIZE = %d\n", MAX_SIZE);
int x = 5;
printf("SQUARE(%d) = %d\n", x, SQUARE(x)); // 25
printf("MAX(3, 7) = %d\n", MAX(3, 7)); // 7
printf("ABS(-10) = %d\n", ABS(-10)); // 10
// Caution: macro side effects
int a = 3;
printf("SQUARE(a++) = %d\n", SQUARE(a++)); // (3)*(4) = 12, not 9!
printf("a after = %d\n", a); // 5
PRINT_INFO("MAX_SIZE", MAX_SIZE);
// #undef — remove a macro definition
#undef MAX_SIZE
// printf("%d", MAX_SIZE); // ERROR: MAX_SIZE not defined
return 0;
}
#include <stdio.h>
#define DEBUG // comment this out to disable debug output
#define VERSION 2
int main() {
int x = 42;
// #ifdef — compile only if DEBUG is defined
#ifdef DEBUG
printf("[DEBUG] x = %d\n", x);
#endif
// #ifndef — compile only if macro is NOT defined
#ifndef RELEASE
printf("Running in development mode\n");
#endif
// #if / #elif / #else — numeric conditions
#if VERSION == 1
printf("Version 1 features\n");
#elif VERSION == 2
printf("Version 2 features\n");
#else
printf("Unknown version\n");
#endif
// Header guard pattern (prevents double inclusion)
// Typically in .h files:
// #ifndef MY_HEADER_H
// #define MY_HEADER_H
// ... header content ...
// #endif
return 0;
}
/*
[DEBUG] x = 42
Running in development mode
Version 2 features
*/
// #pragma once — modern alternative to header guards
// (supported by most compilers: GCC, Clang, MSVC)
// #pragma once
#include <stdio.h>
// Useful debug macro using predefined macros
#define LOG(msg) printf("[%s:%d] %s\n", __FILE__, __LINE__, msg)
int main() {
// Predefined macros
printf("File: %s\n", __FILE__);
printf("Line: %d\n", __LINE__);
printf("Date: %s\n", __DATE__);
printf("Time: %s\n", __TIME__);
// Using LOG macro
LOG("Program started");
int x = 10;
LOG("About to compute");
printf("x = %d\n", x);
LOG("Done");
// #pragma message — print message at compile time
// #pragma message("Compiling main.c...")
// #pragma pack — control struct alignment
// #pragma pack(1) // pack structs with 1-byte alignment
return 0;
}
/*
File: predefined.c
Line: 12
Date: Jan 15 2025
Time: 10:30:00
[predefined.c:16] Program started
x = 10
[predefined.c:19] Done
*/
Ready to Level Up Your Skills?
Explore 500+ free tutorials across 20+ languages and frameworks.