The Preprocessor
The Preprocessor
List of directives :
Macro substitution :
Macro substitution is a process where a macro in the program is replaced
by numbers or expressions, or actual strings.
Syntax:
where:
- There must be at least one blank space between the identifier and value.
All the occurrences of the above macros will be replaced by their respective
values.
Exception: Macro inside a string (quotation marks) does not get replaced.
For example,
#define M 5
total = M * value;
printf (“M = %d\n”, M);
total = 5 * value;
printf(“M = %d*\n”, 5);
#define D 45 - 22
#define A 78 + 32
ratio = D/A;
ratio = 45 - 22 / 78 + 32;
More examples:
#define TEST if(x>y)
#define AND
#define PRINT printf(“Good.\n”);
Syntax:
#define MACRO_NAME(parameter1, parameter2, ...) value
Examples:
#define CUBE(x) ( (x) *(x) *(x) )
In our source code if we have,
volume = CUBE(side);
More examples:
can be called-in by
Nesting of macros:
Placement of one macro in the definition of another macro
Examples:
If there is a statement as
power = SIXTH(x);
(CUBE(x) * CUBE(x))
we can use the following nested call to give the maximum of three values x,
y, and z:
MAX(x, MAX(y, z) )
Undefining a macro:
#undef macro_name ;
This is useful when we want to restrict the definition only to a particular part
of the program.
Example:
#include <stdio.h>
int main() {
printf("Before #undef, VALUE: %d\n", VALUE);
#undef VALUE
return 0;
}
Output:
error: 'VALUE' undeclared (first use in this function)
11 | printf("After #undef, VALUE: %d\n", VALUE);
File inclusion
An external file containing functions or macro definitions can be included as
a part of a program so that we need not rewrite those functions or macro
definitions. This is achieved by the preprocessor directive
#include “filename”
where filename is the name of the file containing the required definitions or
functions.
At this point, the preprocessor inserts the entire contents of filename into
the source code of the program.
When the filename is included within the double quotation marks, the
search for the file is made first in the current directory and then in the
standard directories.
Example:
Create a Header File (myheader.h)
This file contains function declarations.
myheader.h
#ifndef MYHEADER_H
#define MYHEADER_H
void greet();
int add(int a, int b);
#endif
myfunctions.c
#include <stdio.h>
#include "myheader.h"
void greet() {
printf("Hello, Welcome to Turbo\n");
}
main.c
#include <stdio.h>
#include "myheader.h"
int main() {
greet();
int sum = add(10, 20);
printf("Sum: %d\n", sum);
return 0;
}
Output:
Hello, Welcome to Turbo
Sum: 30
#include<filename>
without double quotation marks. In this case, the file is searched only in
the standard directories.
Example:
Case 1: With Include Guards (Correct Way)
File1.h
#ifndef FILE1_H
#define FILE1_H
#include<stdio.h>
#include "file2.h"
void func1() {
printf("This is func1 in file1.h\n");
func2();
}
#endif
File2.h
#ifndef FILE2_H
#define FILE2_H
#include <stdio.h>
void func2() {
printf("This is func2 in file2.h\n");
}
#endif
main.c
#include "file1.h"
#include "file2.h"
int main() {
func1();
return 0;
}
// From file1.h
void func1() {
printf("This is func1 in file1.h\n");
func2();
}
int main() {
func1();
return 0;
}
void func2() {
printf("This is func2 in file2.h\n");
}
main.c
#include "file1.h"
#include "file2.h"
int main() {
func1();
return 0;
}
void func1() {
printf("This is func1 in file1.h\n");
func2();
}
void func2() {
printf("This is func2 in file2.h\n");
}
int main() {
func1();
return 0;
}
Compilation Error:
error: redefinition of ‘func2’
Because:
func2() is defined twice
C does not allow a function to be defined more than once
When we write a large program, it's a good practice to split the code into
multiple files for better organization. Normally, when we split code into
multiple .c files, we need to compile each .c file separately into an
object file (.obj ) and then link them together to create the final
executable.
When we include a .c file inside main.c using #include , the compiler treats
it as if the contents of the .c file were copied directly into main.c. This
means:
Example:
Create main.c
#include <stdio.h>
#include "stats.c"
int main() {
int x = 10, y = 20;
return 0;
}
1. Conditional Compilation
Allows selective compilation of code based on specific conditions.
#ifdef DEBUG
printf("Debug mode is ON\n");
#endif
#ifdef: This checks if a macro is defined. If the macro is defined, the code
following #ifdef up to #endif, or #else, or #elif is compiled.
#else: Used with #if, #ifdef, or #ifndef. If the preceding condition is false,
the compiler includes the code following #else.
#elif: Short for “else if”. Allows for multiple conditional expressions. If the
preceding #if, #ifdef, or #ifndef is false, and the condition in #elif is true, the
code following #elif is compiled.
Example :
#include <stdio.h>
#define NUM 10
int main() {
#if NUM > 5
#endif
return 0;
}
int main() {
printf("NUM is greater than 5\n");
return 0;
}
Output: NUM is greater than 5
#endif
Explanation:
● #ifndef stands for "if not defined".
● It checks whether a macro is not defined before including the code
following it.
● If the macro is not defined, the code block after #ifndef will be
included in the program.
● If the macro is defined, the code block will be skipped.
Example :
#include <stdio.h>
#ifndef MY_MACRO
#define MY_MACRO 10
#endif
int main() {
return 0;
}
#endif
Explanation:
● #ifdef stands for "if defined." It checks whether the macro,
MACRO_NAME has been previously defined using #define.
● If the macro is defined, the code block inside the #ifdef will be
included in the program.
● If the macro is not defined, the code block inside the #ifdef will be
ignored by the preprocessor.
Example:
#include <stdio.h>
#define NUM 10
int main() {
#ifdef NUM
#endif
return 0;
}
int main() {
printf("NUM is defined with value: %d\n", 10);
return 0;
}
Output: NUM is defined with value: 10
Syntax of #elif:
#if CONDITION_1
#elif CONDITION_3
#else
#endif
Key Points:
Example:
#include <stdio.h>
#define NUM 10
int main() {
#if NUM > 15
printf("NUM greater than15\n");
#elif NUM == 10
printf("NUM is equal to 10\n");
#else
printf("NUM is less than 10\n");
#endif
return 0;
}
Explanation:
● We define NUM as 10.
● The #if condition checks if NUM is greater than 15. Since it’s not, it
moves to the next condition.
● The #elif condition checks if NUM is equal to 10. This is true, so it
prints "NUM is equal to 10".
● If neither condition was true, the #else would be executed, but in this
case, it is skipped.
#include <stdio.h>
int main() {
return 0;
}
Output:
NUM is equal to 10
Syntax of #else
The #else directive is used with #if, #ifdef, #elif or #ifndef to specify an
alternative block of code when the condition specified with any of these is
false.
#if CONDITION
// Code if CONDITION is true
#else
// Code if CONDITION is false
#endif
Example:
#include <stdio.h>
#define VALUE 10
int main() {
#if VALUE > 5
printf("VALUE greater than 5\n");
#else
printf("VALUE is 5 or less\n");
#endif
return 0;
}
Preprocessed Code (After Preprocessing):
#include <stdio.h>
int main() {
printf("VALUE greater than 5\n");
return 0;
}
#define FEATURE_ENABLED
int main() {
#ifdef FEATURE_ENABLED
printf("Feature is enabled!\n");
#else
printf("Feature is disabled!\n");
#endif
return 0;
}
#include <stdio.h>
int main() {
printf("Feature is enabled!\n");
return 0;
}
Output:
Feature is enabled!
#define CONFIG
int main() {
#ifndef CONFIG
printf("CONFIG is not defined!\n");
#else
printf("CONFIG is defined!\n");
#endif
return 0;
}
#include <stdio.h>
#define CONFIG
int main() {
printf("CONFIG is defined!\n");
return 0;
}
#define VALUE 20
int main() {
#else
#endif
return 0;
}
Preprocessed Code (After Preprocessing):
#include <stdio.h>
int main() {
printf("VALUE is between 10 and 30\n");
return 0;
}
Expected Output:
VALUE is between 10 and 30