A macro with arguments is a code template defined using #define that looks like a function, but it's handled by the preprocessor before compilation.
Instead of calling a function at runtime, the macro is replaced inline with the actual code during preprocessing.
📌 Syntax
#define MACRO_NAME(parameter1, parameter2, ...) expression_using_parameters✅ Example: Square of a Number
#define SQUARE(x) ((x) * (x))int main() {
int a = 5;
printf("Square: %d\\n", SQUARE(a)); // Becomes ((a) * (a)) → (5 * 5)
}🔄 The macro SQUARE(a) is replaced by ((a) * (a)) before compilation.
⚠️ Common Pitfalls & How to Avoid Them
❌ Without Parentheses – Bug!
#define SQUARE(x) x * xint result = SQUARE(1 + 2); // Becomes 1 + 2 * 1 + 2 = 1 + 2 + 2 = 5 ❌🧠 What actually happened?
result = 1 + 2 * 1 + 2
= 1 + 2 + 2 // (due to operator precedence)
= 5 (Wrong!)✅ Fix: Wrap Parameters & Expression in Parentheses
#define SQUARE(x) ((x) * (x)) // Now: ((1 + 2) * (1 + 2)) = 9 ✔️🧪 More Examples
🔸 Maximum of Two Numbers
#define MAX(a, b) ((a) > (b) ? (a) : (b))int x = 5, y = 9;
printf("Max: %d", MAX(x, y)); // Output: 9🔸 Swap Two Values – Won’t Work as Expected!
#define SWAP(a, b) { int temp = a; a = b; b = temp; }int x = 10, y = 20;
SWAP(x, y);🧨 May work, but:
It creates a variable named
tempevery time → Name collision risk!Multiple statements inside
{}can be dangerous in if-else blocks
✅ Better (with do { } while(0) trick):
define SWAP(a, b) do { int temp = a; a = b; b = temp; } while(0)This makes it behave more like a real function!
🔸 Area of a Circle
#define PI 3.14159
#define AREA_CIRCLE(r) (PI * (r) * (r))float area = AREA_CIRCLE(5); // (3.14159 * 5 * 5)🔸 Min of Three Numbers
#define MIN3(a, b, c) ((a) < (b) ? ((a) < (c) ? (a) : (c)) : ((b) < (c) ? (b) : (c)))🧱 Macro Expansion Process (Step-by-step)
#define MULT(a, b) ((a) * (b))
int x = 2;
int y = 3;
int z = MULT(x + 1, y - 1);🔍 The compiler sees:
int z = ((x + 1) * (y - 1)); // Safe and correctBut without parentheses:
#define MULT(a, b) (a * b)
int z = MULT(x + 1, y - 1); // Becomes: (x + 1 * y - 1)
// Wrong due to operator precedence📌 Key Takeaways – Best Practices
Do ✅ | Don’t ❌ |
|---|---|
Wrap parameters in | Forget parentheses |
Wrap whole expression in | Write long, complex logic |
Use simple expressions | Use multiple statements |
Use | Assume macros do type-checking |
💥 Macro vs Function: When to Use?
Aspect | Macro with Arguments | Function |
|---|---|---|
Speed | Faster (inline substitution) | Slightly slower (call stack) |
Type safety | ❌ No type checking | ✅ Type checking |
Debugging | ❌ Hard to debug | ✅ Easier to trace |
Complexity | Good for 1-line expressions | Good for multi-step logic |