A macro in C is a named piece of replacement text created with the #define directive. When the preprocessor sees that macro name, it replaces it with the defined text before compilation. This means macros are not functions and not variables. They are preprocessor-level substitutions that happen earlier than compilation.
Macros are extremely common in C programming because they can define symbolic constants, create small reusable code patterns, support conditional compilation, and build compiler-friendly abstractions. But they also need care, because macros do not follow function rules, type checking, or runtime semantics. In this article, we will understand macro in C, its syntax, types, common examples, pitfalls, and best practices.
What is Macro in C?
A macro in C is a preprocessor definition created using #define. It tells the preprocessor to replace a name with some other text before the compiler processes the code.
In simple words, a macro is a text substitution rule, not a runtime feature.
A macro expands before compilation. A function runs after compilation.
Syntax of Macro in C
The basic syntax is:
#define MACRO_NAME replacement_textExample:
#define PI 3.14159Whenever the preprocessor sees PI, it replaces it with 3.14159.
How Macro Works in C
- You define a macro with
#define. - The preprocessor scans the source file.
- Every matching macro name is replaced with its definition.
- The compiler then compiles the expanded code.
This means the compiler does not see the macro name in its original form. It usually sees only the expanded result.
Types of Macros in C
| Macro type | Description |
|---|---|
| Object-like macro | Replaces a name with a constant or text value |
| Function-like macro | Looks like a function call and accepts arguments |
| Multi-line macro | Expands into multiple statements |
| Special macro | Uses operators like # or ## |
Object-Like Macro in C
An object-like macro is the simplest kind. It usually behaves like a named constant.
#define MAX_SIZE 100
#define PI 3.14159These are commonly used for sizes, flags, numeric constants, and compile-time configuration values.
Function-Like Macro in C
A function-like macro accepts parameters and expands using those arguments.
#define SQUARE(x) ((x) * (x))When used like SQUARE(5), the preprocessor replaces it with ((5) * (5)).
Macros like this can be fast and convenient, but they are also a major source of bugs if written carelessly.
Why Parentheses Matter in Macros
Macro parameters should almost always be wrapped in parentheses, and the full expansion should usually be wrapped too. Otherwise operator precedence can change the meaning.
| Unsafe macro | Safer macro |
|---|---|
#define SQUARE(x) x * x | #define SQUARE(x) ((x) * (x)) |
Without parentheses, an expression such as SQUARE(a + b) expands incorrectly.
#define BAD_SQUARE(x) x * x
#define GOOD_SQUARE(x) ((x) * (x))Example of Macro in C
The following example shows both a constant-style macro and a function-like macro.
#include <stdio.h>
#define PI 3.14159
#define AREA(r) (PI * (r) * (r))
int main(void)
{
float radius = 5.0f;
printf("%.2f\n", AREA(radius));
return 0;
}Here, the preprocessor expands AREA(radius) before the compiler handles the code.
Macro vs Function in C
| Point | Macro | Function |
|---|---|---|
| Handled by | Preprocessor | Compiler and runtime call mechanism |
| Type checking | No normal function-type checking | Yes |
| Execution | Text substitution before compilation | Runs at program execution time |
| Debugging | Often harder | Usually easier |
| Side effects risk | Higher | Lower in normal use |
Macros can be useful, but many tasks are clearer and safer with normal functions or const variables.
Macro vs const in C
For named constants, beginners often ask whether to use a macro or const.
| Use case | Usually better choice |
|---|---|
| Simple typed numeric constant | const |
| Compile-time symbolic replacement | Macro |
| Text substitution needed before compilation | Macro |
| Readable typed value inside C logic | const |
If type safety and debugger visibility matter more, const is often the better choice.
Multi-Line Macro in C
A macro can span multiple lines using the backslash continuation character.
#define PRINT_SUM(a, b) \
do { \
printf("%d\n", (a) + (b)); \
} while (0)The do { ... } while (0) pattern is commonly used so the macro behaves more safely like a single statement.
Stringizing Operator in Macro
The # operator inside a macro converts an argument into a string literal.
#define STRINGIFY(x) #xThis is useful in logging, debug messages, and generated text.
Token Pasting Operator in Macro
The ## operator joins two tokens together during macro expansion.
#define MAKE_VAR(a, b) a##bThis operator is useful in generated identifiers and certain low-level patterns, but it should be used carefully to keep code readable.
Common Problems with Macros in C
- operator precedence bugs
- multiple evaluation of arguments
- harder debugging
- lack of type checking
- unreadable expansions in large codebases
One especially important problem is side effects.
#define DOUBLE(x) ((x) + (x))If used as DOUBLE(i++), the expression may increment i more than once because the macro argument appears multiple times after expansion.
| Mistake | Problem | Safer idea |
|---|---|---|
| No parentheses | Wrong expression result | Wrap parameters and whole expression |
| Repeated parameter use | Side effects may happen multiple times | Avoid unsafe argument patterns |
| Overusing macros | Readability and debugging suffer | Prefer functions or const when suitable |
| Multi-statement macro without wrapper | Can break control flow | Use do { ... } while (0) |
Best Practices for Macro in C
- Use parentheses carefully in function-like macros.
- Prefer
constor functions when they make code clearer. - Keep macros short, focused, and readable.
- Use multi-line macros carefully with the standard wrapper pattern.
- Avoid macros with hidden side effects.
FAQs
What is macro in C?
A macro in C is a preprocessor definition created with #define that replaces a name with some other text before compilation.
Are macros in C the same as functions?
No. Macros are text substitutions handled by the preprocessor, while functions are compiled program units that run at execution time.
Why are parentheses important in macros?
They prevent precedence bugs and help the expanded macro behave as intended inside larger expressions.
What is the difference between macro and const in C?
A macro is replaced before compilation, while const creates a typed value handled by the compiler.
What does ## mean in C macros?
The ## operator pastes two tokens together during macro expansion.
What does # mean in C macros?
The # operator converts a macro argument into a string literal. This is called stringizing.