Unit 1
Preprocessor
Introduction to Preprocessor in Advanced C
● In Advanced C programming, the preprocessor is an important tool that prepares your source
code before it is actually compiled.
● It is not a part of the compiler but works as a separate step that processes the code according to
certain instructions called preprocessor directives.
● These directives tell the compiler to include files, define constants or macros, conditionally
compile parts of the code, and perform other tasks that help make programs more efficient,
flexible, and easier to maintain.
🧩 Concept of Preprocessor in Advanced C
The preprocessor in C is a program that processes the source code before it is compiled.
It handles special instructions called preprocessor directives, which always begin with the symbol #.
The preprocessor works before the compilation step — it modifies, expands, or prepares the code so that the compiler receives
the final version of the source code for compilation.
⚙ Main Concept
The main concept of the preprocessor is:
“To make the program flexible, readable, and efficient by performing text substitution, file inclusion, and conditional
compilation before the actual compilation starts.”
🧩 Format of Preprocessor Directives in Advanced C
1. A preprocessor directive is an instruction that is processed before the actual compilation of a C program.
2. All preprocessor directives begin with a hash symbol # and do not end with a semicolon.
3. They are executed by the C preprocessor — not by the compiler.
⚡ Rules for Preprocessor Directives
● Must begin with # symbol.
● No semicolon (;) is used at the end.
● Can appear anywhere in the program but are usually at the top.
● The compiler ignores them directly; only the preprocessor handles them.
● They can span multiple lines using a backslash \.
Following is the list of commonly used preprocessor directives and
their functions
[Link]. Directives Functions
1 #define Used to define a macro.
2 #include Used to include a file in the source code program.
3 #undef Used to undefine a macro.
4 Used to include a section of code if a certain macro is defined by
#ifdef
#define.
5 #endif Used to mark the end of #if, #ifdef, and #ifndef.
6 Used to include a section of code if a certain macro is not defined
#ifndef
by #define.
7 #if Check for the specified condition.
File Inclusion Directives(#include)
#include
#include preprocessor directive is used to include the contents of a specified file into the source code before
compilation. It allows you to use functions, constants, and variables from external libraries or header files.
There are two types:
#include <filename> → For system header files
#include "filename" → For user-defined header files
🧾 1. Using Angle Brackets < >
● Used to include standard library header files.
● The preprocessor searches for the file in the system directories where C standard libraries are stored.
✅ Example:
#include <stdio.h> // Includes standard input/output functions
#include <math.h> // Includes mathematical functions like sqrt(), pow()
🧾 2. Using Double Quotes " "
● Used to include user-defined header files (created by the programmer).
● The preprocessor first searches in the current working directory, and if not found, then in system directories.
✅ Example:
#include "myheader.h" // Includes a user-created header file
✨ Example Program
File 1: myheader.h
void greet() {
printf("Welcome to Advanced C Programming!\n");
}
File 2: main.c
#include <stdio.h>
#include "myheader.h"
int main() {
greet(); // Function from user-defined header file
return 0;
}
Output:
Welcome to Advanced C Programming!
✅ In Short (For Notes):
Type Syntax Search Path Example
System Header File #include <filename> System library folder #include <stdio.h>
User-Defined Header File #include "filename" Current working #include "myheader.h"
directory first, then
system folders
🧩 Macro Substitution Directives (#define) in Advanced C
The #define directive is a preprocessor directive used to create macros — symbolic names that represent constants,
expressions, or even code fragments.
🧠 Concept
When the preprocessor encounters a #define directive, it replaces every occurrence of the macro name with its defined value
throughout the code before it is compiled.
It’s like a find-and-replace operation done automatically by the preprocessor.
Syntax / Format
#define MACRO_NAME value
or
#define MACRO_NAME(parameters) expression
📘 Types of Macros
1. Object-like Macros
These act like constants.
✅ Example:
#define PI 3.1416
#define MAX 100
Every occurrence of PI will be replaced by 3.1416 before compilation.
2. Function-like Macros
These look like functions but are replaced by expressions.
✅ Example:
#define AREA(r) (3.1416 * (r) * (r))
#define SQUARE(x) ((x) * (x))
When you write AREA(5), it becomes (3.1416 * (5) * (5)) before compilation.
3. Multi-line Macros
A macro can span multiple lines using the backslash \ symbol.
✅ Example:
#define MESSAGE printf("Welcome to Advanced C Programming!\n"); \
printf("Using Macro Substitution.\n");
🧾 Example Program
#include <stdio.h>
#define PI 3.1416
#define AREA(r) (PI * (r) * (r))
int main() {
float radius = 5;
printf("Area of Circle = %.2f\n", AREA(radius));
return 0;
}
Output:
Area of Circle = 78.54
⚡ Rules for Using #define
1. Must begin with the # symbol.
2. Does not end with a semicolon (;).
3. Macro names are usually written in uppercase (by convention).
4. Macros are replaced before compilation (by the preprocessor).
5. You can use #undef to remove a previously defined macro.
6. Macros do not occupy memory — they are replaced textually.
7. Be careful with expressions; always use parentheses to avoid errors.
🧾 Macro vs Constant
Macro (#define) Constant (const)
Handled by preprocessor Handled by compiler
No data type Has a specific data type
Text substitution Memory allocated
Example: #define PI 3.14 Example: const float PI = 3.14;
✅ In Short (For Notes)
Directive Purpose Example
#define Defines symbolic constants or #define MAX 100
macros
Object-like macro Acts like a constant #define PI 3.14
Function-like macro Acts like a function #define AREA(r) (3.14*(r)*(r))
To remove macro #undef MACRO_NAME #undef PI
🧩 What is Nested Macro in C?
1. A nested macro means using one macro inside another macro.
In other words, one macro calls (or expands) another macro when it is used in a program.
2. It’s just like combining two or more macros together to make the code shorter and reusable.
Concept
● When the preprocessor finds a macro inside another macro,
it first expands the inner macro, then the outer macro.
● This process happens before compilation (in the preprocessing phase).
#include <stdio.h>
#define SQUARE(x) ((x)*(x))
#define CUBE(x) ((SQUARE(x))*(x)) //
Nested macro
int main() {
int n = 3;
printf("Square = %d\n", SQUARE(n));
printf("Cube = %d\n", CUBE(n));
return 0;
}
Output:
Square = 9
Cube = 27
A nested macro is simply a macro that uses another
macro within its definition.
1) What each line does
● #include <stdio.h>
Tells the preprocessor to paste the contents of the standard I/O header so you can use printf().
● #define SQUARE(x) ((x)*(x))
Defines a function-like macro named SQUARE. Every occurrence of SQUARE(some_expr) is textually replaced by
((some_expr)*(some_expr)) before compilation.
● #define CUBE(x) ((SQUARE(x))*(x))
Defines CUBE which uses the macro SQUARE inside it — that's a nested macro. CUBE(a) expands to
((SQUARE(a))*(a)), and then SQUARE(a) itself expands further.
● int n = 3;
Declares an int and initializes it to 3.
● printf("Square = %d\n", SQUARE(n));
The preprocessor replaces SQUARE(n) with ((n)*(n)), so this prints 9.
● printf("Cube = %d\n", CUBE(n));
CUBE(n) expands to ((SQUARE(n))*(n)) → (((n)*(n))*(n)) → ((3*3)*3) → 27, so this prints 27.
Parameterized Macros in Advanced C
🔹 Concept: Parameterized Macros
1. A parameterized macro in C is a macro that takes arguments (parameters) — similar to a function, but it’s processed by the
preprocessor before the program is compiled.
2. The preprocessor replaces the macro name and its parameters with the code you define.
Syntax:
#define MACRO_NAME(parameter1, parameter2, ...) replacement_text
● MACRO_NAME: The name you give to your macro. It's a convention to use uppercase for macro names.
● (parameter1, parameter2, ...): A comma-separated list of parameters that the macro will accept. These
parameters act as placeholders within the replacement_text.
● replacement_text: The code or expression that the preprocessor will substitute in place of the macro call. This text
can include the parameters.
How they work:
During the preprocessing phase (before actual compilation), whenever the preprocessor encounters a call to MACRO_NAME
with arguments, it performs a direct text substitution. It replaces the macro call with the replacement_text, substituting the
provided arguments for the corresponding parameters.
Example:1 In this example:
#include <stdio.h> ● SQUARE(x) is defined as a parameterized macro.
#define SQUARE(x) ((x) * (x)) // Macro to calculate the square ● When SQUARE(num) is encountered in main(), the preprocessor
int main() { replaces it with ((num) * (num)).
int num = 5; ● The expression ((5) * (5)) is then evaluated during compilation,
resulting in 25.
printf("The square of %d is %d\n", num, SQUARE(num)); // Macro
call
return 0;
}
✅ Example 2 – Two Arguments
#include <stdio.h>
#define ADD(a, b) ((a) + (b)) // Macro with two arguments
int main() {
int x = 10, y = 20;
printf("Addition = %d\n", ADD(x, y));
return 0;
}
Output:
Addition = 30
⚙ How it Works Internally
If you write ADD(x, y),
the preprocessor replaces it with ((x) + (y)).
So before compilation, your program looks like:
printf("Addition = %d\n", ((x) + (y)));
This replacement happens before the compiler runs, during preprocessing.
⚠ Important Rules
✅ Always use parentheses in macro definitions.
Example:
#define SQUARE(x) ((x)*(x)) // Correct
#define SQUARE(x) x*x // Wrong
1. Because SQUARE(2+3) →
○ Wrong: 2+3*2+3 = 11 ❌
○ Correct: ((2+3)*(2+3)) = 25 ✅
✅ Example 3
#include <stdio.h>
#define AREA_OF_CIRCLE(r) (3.14 * (r) * (r))
int main() {
float radius = 5;
printf("Area = %.2f\n", AREA_OF_CIRCLE(radius));
return 0;
}
The format %.2f prints the floating value with two decimal places.
Output:
Area = 78.50
💡 Program: Find Maximum Between Two Numbers using Macro with Parameters
#include <stdio.h>
#define MAX(a, b) ((a) > (b) ? (a) : (b)) // Macro with two parameters
int main() {
int x = 10, y = 25;
printf("Maximum = %d\n", MAX(x, y));
return 0;
}
🔍 Explanation
Macro Definition:
#define MAX(a, b) ((a) > (b) ? (a) : (b))
● This defines a macro named MAX that takes two parameters: a and b.
● It uses the conditional (ternary) operator ? : to compare them.
○ If (a) > (b) → result is (a)
○ Else → result is (b)
In main() function:
● x = 10, y = 25
● MAX(x, y) is replaced by ((x) > (y) ? (x) : (y))
● So, it becomes ((10) > (25) ? (10) : (25)) → 25
Output:
Maximum = 25
⚙ How It Works Internally (Preprocessor Expansion)
Before compilation, the preprocessor expands:
printf("Maximum = %d\n", ((x) > (y) ? (x) : (y)));
That’s how macros work — by text substitution before compilation.
Macros Versus Function
Macro Function
Defined using #define preprocessor directive Defined using return_type function_name() syntax
Replaced before compilation (text substitution) Executed during runtime
Slightly slower (function call + return)
Faster (no function call overhead)
#define SQUARE(x) ((x)*(x)) int square(int x) { return x*x; }
Hard to debug (no trace)
Easy to debug
#ERROR/#PRAGMA DIRECTIVES
1. #error Directive
Definition:
The #error directive is a preprocessor directive used to display an error message during compilation.
It helps the programmer stop the compilation process if a certain condition is not met.
✅ Syntax: #include <stdio.h>
#error "error message" #define VERSION 2
#if VERSION < 5
#error "Version too old! Please update."
#endif
int main() {
printf("Program running...\n");
return 0;
}
Explanation:
● The preprocessor checks VERSION < 5.
● Since the condition is true, it shows:
2. #pragma Directive
🔹 Definition:
The #pragma directive gives special instructions to the compiler.
It is compiler-specific — meaning different compilers may support different #pragma commands.
✅ Syntax:
#pragma command
✅ Common Examples:
(a) #pragma startup / #pragma exit
Used to call functions before main() starts and after program ends.
#include <stdio.h>
Output:
void start() { Program is starting...
Inside main function.
printf("Program is starting...\n"); Program is ending...
}
void end() {
printf("Program is ending...\n");
}
#pragma startup start
#pragma exit end
int main() {
printf("Inside main function.\n");
return 0;
}
Conditional Compilation Directives
Conditional compilation directives in C allow sections of code to be included or excluded from compilation based on specific
conditions evaluated by the preprocessor. These directives enable code adaptation for different platforms, debugging, or feature
toggling without modifying the source code directly.
Purpose of Conditional Compilation
● To compile code for different operating systems or hardware.
● To test or debug specific parts of code.
● To include or skip code depending on certain conditions.
#if Directive in C
Definition:
The #if directive is a conditional compilation directive used to check a constant expression or condition.
✅ Syntax: ✅ Example 1: Basic Use of #if
#if condition #include <stdio.h>
#define VALUE 10
// code to compile if condition is true
int main() {
#endif #if VALUE > 5
printf("VALUE is greater than 5\n");
#endif
return 0;
}
Explanation:
The preprocessor checks if VALUE > 5.
Since the condition is true, the statement inside #if is
compiled.
Output:
VALUE is greater than 5
Using #if with #else
#include <stdio.h>
#define NUMBER 4 Output:
int main() { Even number
#if NUMBER % 2 == 0 Explanation:
printf("Even number\n"); ● NUMBER % 2 == 0 → true, so “Even number” is printed.
#else ● The #else part is ignored.
printf("Odd number\n");
#endif
return 0;
}
What is #ifdef Directive
Definition:
The #ifdef (short for “if defined”) directive is a conditional compilation directive.
It checks whether a macro is defined or not using the #define directive.
● If the macro is defined, the compiler includes the code inside the block.
● If the macro is not defined, the compiler skips that part of the code.
✅ Syntax:
#ifdef MACRO_NAME
// code compiled if MACRO_NAME is defined
#endif
It can also be used with #else and #endif:
#ifdef MACRO_NAME
// if defined
#else
// if not defined
#endif
✅ Example 1: Basic Example
#include <stdio.h>
#define DEBUG // Macro defined
int main() {
#ifdef DEBUG
printf("Debug mode is ON\n");
#endif
printf("Program running...\n");
return 0;
}
Explanation:
● #ifdef DEBUG checks if DEBUG is defined.
● Since it is defined, the statement inside is compiled.
Output:
Debug mode is ON
● Program running...
✅ Example 2: Using #ifdef with
#else
#include <stdio.h>
// #define DEBUG // Not defined
int main() {
#ifdef DEBUG
printf("Debug mode is ON\n");
#else
printf("Debug mode is OFF\n");
#endif
return 0;
}
Output:
Debug mode is OFF
Explanation:
Since DEBUG is not defined, the #else part is compiled.
✅ Example 3:
You can use #ifdef to compile different parts of code depending
on platform or version.
#include <stdio.h>
#define WINDOWS // Suppose we are compiling on
Windows
int main() {
#ifdef WINDOWS
printf("Running on Windows\n");
#else
printf("Running on Linux\n");
#endif
return 0;
}
Output:
Running on Windows
#elif Directive
Definition:
The #elif directive stands for “else if” in conditional compilation.
It is used after an #if directive to test another condition if the first #if condition is false.
👉 In simple words,
#elif allows multiple conditions to be checked one after another, just like if–else if–else in normal C programming.
✅ Syntax:
#if condition1
// code if condition1 is true
#elif condition2
// code if condition2 is true
#else
// code if all conditions are false
#endif
✅ Example 1: Using #elif Explanation:
#include <stdio.h>
#define MARKS 70 ● The preprocessor checks conditions in order:
int main() {
1. MARKS >= 90 → false
#if MARKS >= 90
printf("Grade: A+\n");
#elif MARKS >= 75 2. MARKS >= 75 → false
printf("Grade: A\n");
#elif MARKS >= 50 3. MARKS >= 50 → true
printf("Grade: B\n");
#else ● So only the third block is compiled.
printf("Fail\n");
#endif
return 0;
Output:
}
Grade: B
✅ Example 2: Multiple Output:
Conditions Zero
#include <stdio.h>
#define VALUE 0
Explanation:
int main() {
#if VALUE > 0 ● The first condition VALUE > 0 → false
printf("Positive number\n");
#elif VALUE < 0 ● The second condition VALUE < 0 → false
printf("Negative number\n");
#else
● So the compiler includes the #else part → prints "Zero".
printf("Zero\n");
#endif
return 0;
}
#endif Directive
Definition:
The #endif directive is used to mark the end of a conditional compilation block that starts with:
● #if
● #ifdef
● #ifndef
It tells the preprocessor where the conditional compilation block ends.
✅ Syntax:
✅ Example 1: Using #endif with #if
#if condition
// code if condition is true #include <stdio.h>
#endif #define VALUE 10
#ifdef MACRO_NAME int main() {
// code if macro is defined #if VALUE > 5
#endif printf("VALUE is greater than 5\n");
#endif
#ifndef MACRO_NAME return 0;
// code if macro is not defined }
#endif
Explanation:
● The preprocessor checks #if VALUE > 5.
● If true, it compiles the code until it reaches #endif.
● #endif marks the end of the conditional block.
Output:
VALUE is greater than 5
✅ Example 2: Using #endif with #ifdef
#include <stdio.h>
#define DEBUG
int main() {
#ifdef DEBUG
printf("Debug mode is ON\n");
#endif
return 0;
}
Explanation:
● #ifdef DEBUG starts the conditional block.
● #endif ends it.
● Only code between #ifdef and #endif is compiled if DEBUG is defined.
Predefined Macros
Definition:
Predefined macros are built-in macros that are automatically defined by the C compiler.
They provide useful information such as:
● the file name,
● current line number,
● current date and time of compilation,
● and compiler-related information.
🧾 Common Predefined Macros
Macro Name Meaning / Description Example Output
__DATE__ Current date of compilation "Nov 10 2025"
__TIME__ Current time of compilation "10:45:22"
__FILE__ Current file name "main.c"
__LINE__ Current line number in the source code 25
__STDC__ Defined as 1 if compiler follows ANSI C standard 1
✅ Example: Using Predefined Macros
Sample Output:
#include <stdio.h>
File Name: main.c
int main() { Date of Compilation: Nov 10 2025
printf("File Name: %s\n", __FILE__); Time of Compilation: 10:45:22
printf("Date of Compilation: %s\n", __DATE__); Line Number: 6
printf("Time of Compilation: %s\n", __TIME__); ANSI C: 1
printf("Line Number: %d\n", __LINE__);
printf("ANSI C: %d\n", __STDC__);
return 0;
}
Explanation:
● __FILE__ → prints the name of your C source file (e.g., "test.c")
● __DATE__ → shows the date when the program was compiled
● __TIME__ → shows the exact time of compilation
● __LINE__ → shows the current line number (helpful in debugging)
● __STDC__ → prints 1 if your compiler follows the ANSI standard
Assignment 1
[Link] is preprocessor in “c” language? Explain with example.
2. What is macro? Explain macro substitution with example.
3. Explain nested macro in detail.
4. Explain predefined macros with example.
5. Explain any four preprocessor directives.