Skip to main content

Macros vs Functions in C

Both macros and functions let you reuse code — but they work very differently and each has strengths and weaknesses.

Side-by-Side Comparison

FeatureMacro (#define)Function
Processed byPreprocessorCompiler
Type checkingNoneFull
SpeedFaster — inlinedSlight call overhead
Code sizeLargerSmaller
DebuggingHard — no name in binaryEasy — shows in stack trace
Side effectsArgs may run multiple timesArgs run once
ScopeFile-wideNormal C scope rules
RecursionNot possibleYes
Return valueAn expressionreturn statement

The Side Effect Problem

A macro evaluates its argument expression every time it appears in the expansion:
#define SQUARE(x)  ((x) * (x))

int i = 3;
int result = SQUARE(i++);
// Expands to: ((i++) * (i++))  — i incremented TWICE → undefined behavior!
A function does not have this problem:
int square(int x) { return x * x; }

int i = 3;
int result = square(i++);   // i++ evaluated once → result = 9, i = 4

Example: Same Task, Two Ways

As a macro:
#define MAX(a, b)  ((a) > (b) ? (a) : (b))
As a function:
int max(int a, int b) {
    return a > b ? a : b;
}
The function is safer and debuggable; the macro is slightly faster and works on any comparable type.

When to Use Each

Use a macro when:
  • You need a simple constant (#define PI 3.14159)
  • You want to work on any type without templates (MAX(a, b))
  • You need compile-time conditional code (#ifdef DEBUG)
  • You need include guards (#ifndef HEADER_H)
Use a function when:
  • The logic is complex or more than one line
  • You need type safety
  • The argument might have side effects
  • You need recursion
  • Debugging matters

inline Functions (C99+)

C99 introduced inline functions — they give you function-level safety and macro-level speed:
static inline int square(int x) {
    return x * x;
}
The compiler can expand the function body at the call site (like a macro) while still enforcing types and proper argument evaluation. For most modern C code, inline functions are preferred over functional macros.