# Macros & Conditional Compilation (How the Preprocessor Really Works)

In the previous lesson, you learned:

*   What the preprocessor is
    
*   How `#include` works
    
*   How `#define` replaces text
    

Now we go deeper.

This lesson is where things become powerful (and a bit tricky):

> **Macros and conditional compilation**

## 1\. What is a Macro?

A macro is created using:

```c
#define
```

It tells the preprocessor:

> “Replace this name with something else before compilation”

## 🔹 Example (Object-like Macro)

```c
#define PI 3.14
```

Usage:

```c
float area = PI * r * r;
```

Before compilation:

```c
float area = 3.14 * r * r;
```

## 2\. Macro Expansion (Key Idea)

> Macro expansion is just **text substitution**

The preprocessor does NOT evaluate logic.

It simply replaces text.

### Example

```c
#define X 5

int a = X + 2;
```

Becomes:

```c
int a = 5 + 2;
```

## 3\. Function-Like Macros

Macros can also look like functions.

## 🔹 Example

```c
#define SQUARE(x) ((x) * (x))
```

Usage:

```c
int result = SQUARE(3);
```

Becomes:

```c
int result = ((3) * (3));
```

## 4\. Why Parentheses Matter ⚠️

Without parentheses:

```c
#define SQUARE(x) x * x
```

Then:

```c
int result = SQUARE(1 + 2);
```

Becomes:

```c
int result = 1 + 2 * 1 + 2;
```

👉 Wrong result!

### Correct Version

```c
#define SQUARE(x) ((x) * (x))
```

👉 Always use parentheses in macros

## 5\. Macro Pitfalls (Very Important)

Macros are powerful but risky:

*   ❌ No type checking
    
*   ❌ Can behave unexpectedly
    
*   ❌ Harder to debug
    

### Example Problem

```c
#define DOUBLE(x) (x + x)

int result = DOUBLE(2 * 3);
```

Becomes:

```c
(2 * 3 + 2 * 3)  // works, but can be confusing
```

## 6\. Conditional Compilation

The preprocessor can decide:

> **Which parts of your code should be compiled**

## 🔹 Basic Example

```c
#ifdef DEBUG
printf("Debug mode\n");
#endif
```

👉 This code runs only if `DEBUG` is defined.

## 7\. Common Conditional Directives

* * *

### `#ifdef`

```c
#ifdef FLAG
```

Checks if a macro is defined.

### `#ifndef`

```c
#ifndef FLAG
```

Checks if a macro is NOT defined.

### `#if`, `#else`, `#endif`

```c
#if VERSION > 1
    // new version
#else
    // old version
#endif
```

## 8\. Include Guards (Very Important)

When you include a header file multiple times, errors can occur.

## 🔹 Solution: Include Guards

```c
#ifndef MAIN_H
#define MAIN_H

// code here

#endif
```

### Why this works:

*   First time → included
    
*   Second time → skipped
    

👉 Prevents duplicate definitions

## 9\. Putting It Together

Example combining everything:

```c
#include <stdio.h>

#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define DEBUG

int main(void)
{
    int x = 10;
    int y = 20;

    int result = MAX(x, y);

#ifdef DEBUG
    printf("Debug: x=%d, y=%d\n", x, y);
#endif

    return 0;
}
```

## 10\. Key Insight

> The preprocessor controls what code the compiler sees

It can:

*   include code
    
*   remove code
    
*   replace code
    

Before compilation even starts.

## 11\. Macros vs Functions

| Macros | Functions |
| --- | --- |
| Faster (no call overhead) | Safer |
| No type checking | Type checking |
| Harder to debug | Easier to debug |

* * *

### When to use macros:

*   constants
    
*   simple expressions
    

* * *

### When to use functions:

*   complex logic
    
*   safer operations
    

## 12\. Practice Thinking

Try to reason through these:

1.  What happens if you define:
    
    ```c
    #define A 10
    int x = A * 2;
    ```
    
2.  Why do we use parentheses in macros?
    
3.  What happens if `DEBUG` is not defined in:
    

```c
#ifdef DEBUG
printf("Hello");
#endif
```

* * *

## Key Ideas to Remember

*   Macros are text replacements
    
*   Function-like macros must use parentheses
    
*   Conditional compilation controls what code runs
    
*   Include guards prevent duplicate inclusion
    
*   Macros are powerful but must be used carefully
    

## What’s Next

Now that you understand macros and conditional compilation, the final step is:

> **How the preprocessor is used in real programs**

In the next lesson, you’ll learn:

*   predefined macros (`__FILE__`, `__LINE__`)
    
*   real-world use cases
    
*   how this connects to your project
    

That’s where everything becomes practical.
