Given 3 integer values, arrange those 3 values in ascending order using macros.
This problem introduces macros - a powerful C++ preprocessor feature that allows text substitution before compilation. Unlike functions, macros are expanded at compile-time!
condition ? true_value : false_value
Input: a = 30, b = 10, c = 20 Step 1: Find Minimum MIN(a, MIN(b, c)) MIN(30, MIN(10, 20)) MIN(30, 10) = 10 ✓ Step 2: Find Maximum MAX(a, MAX(b, c)) MAX(30, MAX(10, 20)) MAX(30, 20) = 30 ✓ Step 3: Calculate Middle mid = a + b + c - min - max mid = 30 + 10 + 20 - 10 - 30 mid = 60 - 40 = 20 ✓ Output: 10 < 20 < 30
Accept three integer values as a input
Print the output as "min < mid < max"
Using only macros -10^15 <= INPUT <= 10^15
#include <iostream> using namespace std; // Macros to find maximum and minimum of two numbers #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b)) int main() { long long a, b, c; cin >> a >> b >> c; // Find minimum, maximum, and middle using macros long long minimum = MIN(a, MIN(b, c)); long long maximum = MAX(a, MAX(b, c)); long long mid = a + b + c - minimum - maximum; cout << minimum << " < " << mid << " < " << maximum << endl; return 0; }
What is a Macro?
A macro is a preprocessor directive that performs text substitution before the code is compiled. The #define
directive creates a macro.
// Macro definition syntax: #define MACRO_NAME(parameters) (replacement_text) // Our MAX macro: #define MAX(a,b) ((a)>(b)?(a):(b)) ↓ ↓ macro name replacement // When you write: result = MAX(10, 20); // Preprocessor replaces it with: result = ((10)>(20)?(10):(20)); // Evaluates to 20
Why Parentheses are Important:
// ❌ BAD: Without parentheses #define MAX(a,b) a>b?a:b // Problem with: MAX(x+1, y+1) // Expands to: x+1>y+1?x+1:y+1 // Due to operator precedence, this behaves unexpectedly! // ✅ GOOD: With parentheses #define MAX(a,b) ((a)>(b)?(a):(b)) // Now: MAX(x+1, y+1) // Expands to: ((x+1)>(y+1)?(x+1):(y+1)) // Works correctly regardless of what a and b are!
Syntax: condition ? value_if_true : value_if_false
// Ternary operator breakdown: (a) > (b) ? (a) : (b) ↓ ↓ ↓ ↓ | | | └── Return b if condition is false | | └─────── Return a if condition is true | └──────────── Comparison operator └────────────────── Operands being compared // Example: MAX(10, 20) ((10)>(20) ? (10) : (20)) ↓ false (10 is not > 20) ↓ returns 20 ✓
Ternary vs If-Else:
// Using if-else: int max; if (a > b) max = a; else max = b; // Using ternary (more concise): int max = (a > b) ? a : b;
Formula: mid = a + b + c - minimum - maximum
Why This Works:
// Given three numbers: a, b, c // Sum of all three: a + b + c // If we subtract the smallest and largest: // (a + b + c) - min - max = middle value // Example: 10, 20, 30 mid = 10 + 20 + 30 - 10 - 30 = 60 - 40 = 20 ✓ // Another example: 50, 10, 30 mid = 50 + 10 + 30 - 10 - 50 = 90 - 60 = 30 ✓ // This is a mathematical property: // Total sum minus extremes = middle value
Visual Representation:
min mid max ↓ ↓ ↓ [10] ←───→ [20] ←───→ [30] Sum = 10 + 20 + 30 = 60 60 - 10 - 30 = 20 (middle value)
#define
? :
Aspect | Macros (#define) | Functions |
---|---|---|
Processing Time | Compile-time (preprocessor) | Runtime |
Type Safety | ❌ No type checking | ✅ Type checked |
Code Size | Larger (code duplicated) | Smaller (single copy) |
Speed | Faster (no call overhead) | Slightly slower (call overhead) |
Debugging | Harder to debug | Easier to debug |
Side Effects | ⚠️ Can have issues | ✅ Safe |
When to Use Each:
inline
functions or constexpr
over macros when possible1. Side Effects with Multiple Evaluation:
// ⚠️ WARNING: Arguments are evaluated multiple times! #define MAX(a,b) ((a)>(b)?(a):(b)) int x = 5, y = 10; int result = MAX(x++, y++); // Expands to: ((x++)>(y++)?(x++):(y++)) // x++ is evaluated TWICE! (once in condition, once in result) // This leads to unexpected behavior! // ✅ SOLUTION: Don't use macros with expressions that have side effects
2. Operator Precedence Issues:
// ❌ BAD: No parentheses around parameters #define SQUARE(x) x*x int result = SQUARE(2+3); // Expands to: 2+3*2+3 = 2+6+3 = 11 (WRONG!) // ✅ GOOD: Parentheses around parameters #define SQUARE(x) ((x)*(x)) int result = SQUARE(2+3); // Expands to: ((2+3)*(2+3)) = 5*5 = 25 (CORRECT!)
3. No Namespace or Scope:
// Macros don't respect scope - they're global! #define MAX(a,b) ((a)>(b)?(a):(b)) // This MAX will be replaced EVERYWHERE in the code // Even inside string literals (in older compilers)
Modern C++ prefers inline
or constexpr
functions over macros:
// Modern approach: inline function (type-safe) inline long long max_func(long long a, long long b) { return (a > b) ? a : b; } // C++14 and later: constexpr (compile-time when possible) constexpr long long max_func(long long a, long long b) { return (a > b) ? a : b; } // C++14: Can use std::max directly #include <algorithm> auto result = std::max({a, b, c});
Why this is better:
However, macros are still useful for:
#ifdef
)#ifdef
assert()
is a macro)LOG_ERROR
, LOG_DEBUG
macros#define
? :
)ABS(x)
SWAP(a,b)
CLAMP(x,min,max)
macro (limit value to range)a+b+c-min-max
with different inputs-E
flag to see macro expansions