C Preprocessor Macros Cheat Sheet
Details the C preprocessor: object-like and function-like macros, conditional compilation, include guards, and stringizing and token-pasting operators.
2 PagesIntermediateApr 15, 2026
Object-like and Function-like Macros
Text substitution performed before compilation.
c
#define PI 3.14159265358979 // Object-like macro (constant)#define MAX(a, b) ((a) > (b) ? (a) : (b)) // Function-like macro#define SQUARE(x) ((x) * (x)) // Always parenthesize params and resultdouble area = PI * SQUARE(5); // Expands safely thanks to the parensint m = MAX(3, 7); // Expands to ((3) > (7) ? (3) : (7))
Conditional Compilation
Include or exclude code based on compile-time conditions.
c
#define DEBUG 1#if DEBUG #define LOG(msg) printf("[DEBUG] %s\n", msg)#else #define LOG(msg)#endif#ifndef HEADER_H#define HEADER_H// header contents go here (include guard)#endif#ifdef _WIN32 // Windows-specific code#elif defined(__linux__) // Linux-specific code#endif
Stringizing and Token Pasting
The # and ## preprocessor operators.
c
#define STRINGIFY(x) #x // Turns an argument into a string literal#define CONCAT(a, b) a##b // Pastes two tokens togetherprintf("%s\n", STRINGIFY(hello)); // Prints: helloint CONCAT(var, 1) = 10; // Expands to: int var1 = 10;#define VERSION_MAJOR 1#define VERSION_MINOR 2// Adjacent string literals concatenate at compile timeconst char *ver = STRINGIFY(VERSION_MAJOR) "." STRINGIFY(VERSION_MINOR);
Pitfalls & Good Practices
Rules of thumb for writing safe macros.
- Parenthesize everything- Wrap macro parameters and the whole expansion in parens to avoid operator-precedence bugs
- No side effects- MAX(i++, j) evaluates an argument twice — avoid expressions with side effects in macro args
- Macros vs functions- Macros are text substitution at compile time: no type checking and no function call overhead
- Include guards- #ifndef / #define / #endif prevents a header from being included more than once per translation unit
- #pragma once- A non-standard but widely supported alternative to manual include guards
- Line continuation- A trailing backslash (\) continues a #define across multiple lines
- Variadic macros- #define LOG(fmt, ...) printf(fmt, __VA_ARGS__) accepts a variable argument list (C99)
Pro Tip
Wrap multi-statement macros in a do { ... } while(0) block so they act like a single statement and don't silently break when used inside an unbraced if/else.
Was this cheat sheet helpful?
Explore Topics
#CPreprocessorMacros#CPreprocessorMacrosCheatSheet#Programming#Intermediate#Object#Like#Function#Macros#OOP#Functions#CheatSheet#SkillVeris