0% found this document useful (0 votes)
7 views

Unit 4

The document explains dynamic memory allocation in C programming, detailing the use of functions like malloc(), calloc(), realloc(), and free() for managing memory during runtime. It provides syntax, examples, and output for each function, illustrating how to allocate, initialize, and deallocate memory. The document emphasizes the importance of freeing dynamically allocated memory to prevent memory leaks.

Uploaded by

kavinasingh2307
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

Unit 4

The document explains dynamic memory allocation in C programming, detailing the use of functions like malloc(), calloc(), realloc(), and free() for managing memory during runtime. It provides syntax, examples, and output for each function, illustrating how to allocate, initialize, and deallocate memory. The document emphasizes the importance of freeing dynamically allocated memory to prevent memory leaks.

Uploaded by

kavinasingh2307
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 49

Unit 4

Dynamic Memory Allocation


As you know, an array is a collection of a fixed number of values. Once the size of an array is
declared, you cannot change it.
Sometimes the size of the array you declared may be insufficient. To solve this issue, you can
allocate memory manually during run-time. This is known as dynamic memory allocation in C
programming.
To allocate memory dynamically, library functions are malloc(), calloc(), realloc() and free() are
used. These functions are defined in the <stdlib.h> header file.

C malloc()
The name "malloc" stands for memory allocation.
The malloc() function reserves a block of memory of the specified number of bytes. And, it
returns a pointer of void which can be casted into pointers of any form.
Syntax of malloc()
ptr = (castType*) malloc(size);

Example
ptr = (float*) malloc(100 * sizeof(float));

The above statement allocates 400 bytes of memory. It's because the size of float is 4 bytes. And,
the pointer ptr holds the address of the first byte in the allocated memory.
The expression results in a NULL pointer if the memory cannot be allocated.

C calloc()
The name "calloc" stands for contiguous allocation.
The malloc() function allocates memory and leaves the memory uninitialized, whereas the
calloc() function allocates memory and initializes all bits to zero.

Syntax of calloc()
ptr = (castType*)calloc(n, size);

Example:
ptr = (float*) calloc(25, sizeof(float));
The above statement allocates contiguous space in memory for 25 elements of type float.

C free()
Dynamically allocated memory created with either calloc() or malloc() doesn't get freed on their
own. You must explicitly use free() to release the space.
Syntax of free()
free(ptr);
This statement frees the space allocated in the memory pointed by ptr.

Example 1: malloc() and free()


// Program to calculate the sum of n numbers entered by the user
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, i, *ptr, sum = 0;
printf("Enter number of elements: ");
scanf("%d", &n);

ptr = (int*) malloc(n * sizeof(int));

// if memory cannot be allocated


if(ptr == NULL) {
printf("Error! memory not allocated.");
exit(0);
}

printf("Enter elements: ");


for(i = 0; i < n; ++i)
{
scanf("%d", ptr + i);
sum += *(ptr + i);
}

printf("Sum = %d", sum);

// deallocating the memory


free(ptr);

return 0;
}

Output
Enter number of elements: 3
Enter elements: 100
20
36
Sum = 156
Here, we have dynamically allocated the memory for n number of int.

Example 2: calloc() and free()


// Program to calculate the sum of n numbers entered by the user
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, i, *ptr, sum = 0;
printf("Enter number of elements: ");
scanf("%d", &n);

ptr = (int*) calloc(n, sizeof(int));


if(ptr == NULL) {
printf("Error! memory not allocated.");
exit(0);
}

printf("Enter elements: ");


for(i = 0; i < n; ++i) {
scanf("%d", ptr + i);
sum += *(ptr + i);
}

printf("Sum = %d", sum);


free(ptr);
return 0;
}
Output
Enter number of elements: 3
Enter elements: 100
20
36
Sum = 156

C realloc()
If the dynamically allocated memory is insufficient or more than required, you can change the
size of previously allocated memory using the realloc() function.
Syntax of realloc()
ptr = realloc(ptr, x);
Here, ptr is reallocated with a new size x.

Example 3: realloc()
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *ptr, i , n1, n2;
printf("Enter size: ");
scanf("%d", &n1);

ptr = (int*) malloc(n1 * sizeof(int));

printf("Addresses of previously allocated memory:\n");


for(i = 0; i < n1; ++i)
printf("%pc\n",ptr + i);

printf("\nEnter the new size: ");


scanf("%d", &n2);

// rellocating the memory


ptr = realloc(ptr, n2 * sizeof(int));
printf("Addresses of newly allocated memory:\n");
for(i = 0; i < n2; ++i)
printf("%pc\n", ptr + i);

free(ptr);

return 0;
}

Output
Enter size: 2
Addresses of previously allocated memory:
26855472
26855476

Enter the new size: 4


Addresses of newly allocated memory:
26855472
26855476
26855480
26855484

OR
Dynamic Memory Allocation in C using malloc(), calloc(), free() and
realloc()
C is a structured language, it has some fixed rules for programming. One of them includes
changing the size of an array. An array is a collection of items stored at contiguous memory
locations.

As can be seen, the length (size) of the array above is 9. But what if there is a requirement to
change this length (size)? For example,
 If there is a situation where only 5 elements are needed to be entered in this array. In
this case, the remaining 4 indices are just wasting memory in this array. So there is a
requirement to lessen the length (size) of the array from 9 to 5.
 Take another situation. In this, there is an array of 9 elements with all 9 indices filled.
But there is a need to enter 3 more elements in this array. In this case, 3 indices more
are required. So the length (size) of the array needs to be changed from 9 to 12.
This procedure is referred to as Dynamic Memory Allocation in C.
Therefore, C Dynamic Memory Allocation can be defined as a procedure in which the size of a
data structure (like Array) is changed during the runtime.
C provides some functions to achieve these tasks. There are 4 library functions provided by C
defined under <stdlib.h> header file to facilitate dynamic memory allocation in C programming.
They are:
1. malloc()
2. calloc()
3. free()
4. realloc()
Let’s look at each of them in greater detail.
C malloc() method
The “malloc” or “memory allocation” method in C is used to dynamically allocate a single
large block of memory with the specified size. It returns a pointer of type void which can be cast
into a pointer of any form. It doesn’t Initialize memory at execution time so that it has initialized
each block with the default garbage value initially.
Syntax of malloc() in C
ptr = (cast-type*) malloc(byte-size)
For Example:

ptr = (int*) malloc(100 * sizeof(int));


Since the size of int is 4 bytes, this statement will allocate 400 bytes of memory. And, the pointer
ptr holds the address of the first byte in the allocated memory.

If space is insufficient, allocation fails and returns a NULL pointer.


Example of malloc() in C

#include <stdio.h>
#include <stdlib.h>

int main()
{

// This pointer will hold the


// base address of the block created
int* ptr;
int n, i;

// Get the number of elements for the array


printf("Enter number of elements:");
scanf("%d",&n);
printf("Entered number of elements: %d\n", n);

// Dynamically allocate memory using malloc()


ptr = (int*)malloc(n * sizeof(int));

// Check if the memory has been successfully


// allocated by malloc or not
if (ptr == NULL) {
printf("Memory not allocated.\n");
exit(0);
}
else {
// Memory has been successfully allocated
printf("Memory successfully allocated using malloc.\n");

// Get the elements of the array


for (i = 0; i < n; ++i) {
ptr[i] = i + 1;
}

// Print the elements of the array


printf("The elements of the array are: ");
for (i = 0; i < n; ++i) {
printf("%d, ", ptr[i]);
}
}

return 0;
}

Output
Enter number of elements: 5
Memory successfully allocated using malloc.
The elements of the array are: 1, 2, 3, 4, 5,

C calloc() method
1. “calloc” or “contiguous allocation” method in C is used to dynamically allocate the
specified number of blocks of memory of the specified type. it is very much similar to
malloc() but has two different points and these are:
2. It initializes each block with a default value ‘0’.
3. It has two parameters or arguments as compare to malloc().
Syntax of calloc() in C
ptr = (cast-type*)calloc(n, element-size);
here, n is the no. of elements and element-size is the size of each element.

For Example:
ptr = (float*) calloc(25, sizeof(float));
This statement allocates contiguous space in memory for 25 elements each with the size of the
float.
If space is insufficient, allocation fails and returns a NULL pointer.
Example of calloc() in C

#include <stdio.h>
#include <stdlib.h>

int main()
{

// This pointer will hold the


// base address of the block created
int* ptr;
int n, i;

// Get the number of elements for the array


n = 5;
printf("Enter number of elements: %d\n", n);

// Dynamically allocate memory using calloc()


ptr = (int*)calloc(n, sizeof(int));

// Check if the memory has been successfully


// allocated by calloc or not
if (ptr == NULL) {
printf("Memory not allocated.\n");
exit(0);
}
else {

// Memory has been successfully allocated


printf("Memory successfully allocated using calloc.\n");
// Get the elements of the array
for (i = 0; i < n; ++i) {
ptr[i] = i + 1;
}

// Print the elements of the array


printf("The elements of the array are: ");
for (i = 0; i < n; ++i) {
printf("%d, ", ptr[i]);
}
}

return 0;
}

Output
Enter number of elements: 5
Memory successfully allocated using calloc.
The elements of the array are: 1, 2, 3, 4, 5,

C free() method
“free” method in C is used to dynamically de-allocate the memory. The memory allocated using
functions malloc() and calloc() is not de-allocated on their own. Hence the free() method is used,
whenever the dynamic memory allocation takes place. It helps to reduce wastage of memory by
freeing it.
Syntax of free() in C
free(ptr);
Example of free() in C

#include <stdio.h>
#include <stdlib.h>

int main()
{

// This pointer will hold the


// base address of the block created
int *ptr, *ptr1;
int n, i;

// Get the number of elements for the array


n = 5;
printf("Enter number of elements: %d\n", n);

// Dynamically allocate memory using malloc()


ptr = (int*)malloc(n * sizeof(int));

// Dynamically allocate memory using calloc()


ptr1 = (int*)calloc(n, sizeof(int));

// Check if the memory has been successfully


// allocated by malloc or not
if (ptr == NULL || ptr1 == NULL) {
printf("Memory not allocated.\n");
exit(0);
}
else {

// Memory has been successfully allocated


printf("Memory successfully allocated using malloc.\n");

// Free the memory


free(ptr);
printf("Malloc Memory successfully freed.\n");

// Memory has been successfully allocated


printf("\nMemory successfully allocated using calloc.\n");

// Free the memory


free(ptr1);
printf("Calloc Memory successfully freed.\n");
}

return 0;
}

Output
Enter number of elements: 5
Memory successfully allocated using malloc.
Malloc Memory successfully freed.

Memory successfully allocated using calloc.


Calloc Memory successfully freed.

C realloc() method
“realloc” or “re-allocation” method in C is used to dynamically change the memory allocation
of a previously allocated memory. In other words, if the memory previously allocated with the
help of malloc or calloc is insufficient, realloc can be used to dynamically re-allocate memory.
re-allocation of memory maintains the already present value and new blocks will be initialized
with the default garbage value.
Syntax of realloc() in C
ptr = realloc(ptr, newSize);
where ptr is reallocated with new size 'newSize'.

If space is insufficient, allocation fails and returns a NULL pointer.


Example of realloc() in C
 C

#include <stdio.h>
#include <stdlib.h>

int main()
{

// This pointer will hold the


// base address of the block created
int* ptr;
int n, i;

// Get the number of elements for the array


n = 5;
printf("Enter number of elements: %d\n", n);

// Dynamically allocate memory using calloc()


ptr = (int*)calloc(n, sizeof(int));

// Check if the memory has been successfully


// allocated by malloc or not
if (ptr == NULL) {
printf("Memory not allocated.\n");
exit(0);
}
else {

// Memory has been successfully allocated


printf("Memory successfully allocated using calloc.\n");

// Get the elements of the array


for (i = 0; i < n; ++i) {
ptr[i] = i + 1;
}

// Print the elements of the array


printf("The elements of the array are: ");
for (i = 0; i < n; ++i) {
printf("%d, ", ptr[i]);
}

// Get the new size for the array


n = 10;
printf("\n\nEnter the new size of the array: %d\n", n);

// Dynamically re-allocate memory using realloc()


ptr = (int*)realloc(ptr, n * sizeof(int));

// Memory has been successfully allocated


printf("Memory successfully re-allocated using realloc.\n");

// Get the new elements of the array


for (i = 5; i < n; ++i) {
ptr[i] = i + 1;
}

// Print the elements of the array


printf("The elements of the array are: ");
for (i = 0; i < n; ++i) {
printf("%d, ", ptr[i]);
}

free(ptr);
}

return 0;
}

Output
Enter number of elements: 5
Memory successfully allocated using calloc.
The elements of the array are: 1, 2, 3, 4, 5,

Enter the new size of the array: 10


Memory successfully re-allocated using realloc.
The elements of the array are: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,

One another example for realloc() method is:

#include <stdio.h>
#include <stdlib.h>
int main()
{
int index = 0, i = 0, n,
*marks; // this marks pointer hold the base address
// of the block created
int ans;
marks = (int*)malloc(sizeof(
int)); // dynamically allocate memory using malloc
// check if the memory is successfully allocated by
// malloc or not?
if (marks == NULL) {
printf("memory cannot be allocated");
}
else {
// memory has successfully allocated
printf("Memory has been successfully allocated by "
"using malloc\n");
printf("\n marks = %pc\n",
marks); // print the base or beginning
// address of allocated memory
do {
printf("\n Enter Marks\n");
scanf("%d", &marks[index]); // Get the marks
printf("would you like to add more(1/0): ");
scanf("%d", &ans);

if (ans == 1) {
index++;
marks = (int*)realloc(
marks,
(index + 1)
* sizeof(
int)); // Dynamically reallocate
// memory by using realloc
// check if the memory is successfully
// allocated by realloc or not?
if (marks == NULL) {
printf("memory cannot be allocated");
}
else {
printf("Memory has been successfully "
"reallocated using realloc:\n");
printf(
"\n base address of marks are:%pc",
marks); ////print the base or
///beginning address of
///allocated memory
}
}
} while (ans == 1);
// print the marks of the students
for (i = 0; i <= index; i++) {
printf("marks of students %d are: %d\n ", i,
marks[i]);
}
free(marks);
}
return 0;
}
Output:

Arrays of Unknown or Varying Size:


Let's delve into the topic of arrays of unknown or varying size in the C programming language.
In C, arrays are traditionally declared with a fixed size, known at compile-time. However, there
are scenarios where the size of an array is not known beforehand, and it needs to be determined
during runtime. This is where the concept of arrays of varying size comes into play.
One way to handle arrays of varying size is through dynamic memory allocation using pointers
and functions like `malloc`, `calloc`, and `realloc`. Here's an overview:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *dynamicArray;
int size;

// Get the size of the array from the user


printf("Enter the size of the array: ");
scanf("%d", &size);

// Dynamically allocate memory for the array


dynamicArray = (int *)malloc(size * sizeof(int));

if (dynamicArray == NULL) {
printf("Memory allocation failed\n");
return 1; // Exit the program with an error code
}

// Input elements into the array


for (int i = 0; i < size; ++i) {
printf("Enter element %d: ", i + 1);
scanf("%d", &dynamicArray[i]);
}

// Display the elements of the array


printf("Elements of the array:\n");
for (int i = 0; i < size; ++i) {
printf("%d ", dynamicArray[i]);
}

// Release the allocated memory


free(dynamicArray);

return 0; // Exit the program successfully


}
In this example, we use `malloc` to dynamically allocate memory for an array based on the user's
input. The `sizeof(int)` ensures that the correct amount of memory is allocated for each element.
After using the array, it's crucial to free the allocated memory using the `free` function to avoid
memory leaks.
Arrays of varying size are particularly useful when dealing with data structures that can grow or
shrink dynamically during program execution, providing flexibility and efficient memory usage.
It's essential to emphasize the importance of proper memory management when working with
dynamically allocated arrays to prevent memory-related issues. Additionally, discussing error
handling and potential pitfalls in such scenarios will enhance the students' understanding.

Structure: Declaring Structures, union, Comparison between


Structure and Union.
Structures in C is a user-defined data type available in C that allows to combining of data
items of different kinds. Structures are used to represent a record.

Defining a structure: To define a structure, you must use the struct statement. The struct
statement defines a new data type, with more than or equal to one member. The format of the
struct statement is as follows:

struct [structure name]


{
member definition;
member definition;
...
member definition;
};
(OR)
struct [structure name]
{
member definition;
member definition;
...
member definition;
}structure variable declaration;
Union in C : is a special data type available in C that allows storing different data types in the
same memory location. You can define a union with many members, but only one member can
contain a value at any given time. Unions provide an efficient way of using the same memory
location for multiple purposes.

Defining a Union: To define a union, you must use the union statement in the same way as
you did while defining a structure. The union statement defines a new data type with more than
one member for your program. The format of the union statement is as follows:

union [union name]


{
member definition;
member definition;
...
member definition;
};
(OR)
union [union name]
{
member definition;
member definition;
...
member definition;
}union variable declaration;
Similarities Between Structure and Union
1. Both are user-defined data types used to store data of different types as a single unit.
2. Their members can be objects of any type, including other structures and unions
or arrays. A member can also consist of a bit field.
3. Both structures and unions support only assignment = and sizeof operators. The two
structures or unions in the assignment must have the same members and member
types.
4. A structure or a union can be passed by value to functions and returned by value by
functions. The argument must have the same type as the function parameter. A
structure or union is passed by value just like a scalar variable as a corresponding
parameter.
5. ‘.’ operator or selection operator, which has one of the highest precedences, is used
for accessing member variables inside both the user-defined datatypes.
Differences between Structure and Union
Differences between Structure and Union are as shown below in tabular format as shown
below as follows:

C program to illustrate differences between structure and Union:

#include <stdio.h>
#include <string.h>

// Define a structure named Student


struct Student {
char name[50];
int age;
float marks;
};

// Define a union named Data


union Data {
int integerData;
float floatData;
char charData;
};

int main() {
// Example of using a structure
struct Student student1;
strcpy(student1.name, "John Doe");
student1.age = 20;
student1.marks = 85.5;

// Displaying information from the structure


printf("Student Information (Structure):\n");
printf("Name: %s\n", student1.name);
printf("Age: %d\n", student1.age);
printf("Marks: %.2f\n", student1.marks);
printf("\n");

// Example of using a union


union Data data1;
data1.integerData = 42;

// Displaying information from the union


printf("Data Information (Union):\n");
printf("Integer Data: %d\n", data1.integerData);

// Modifying the union's content by assigning a float


data1.floatData = 3.14;
printf("Float Data: %.2f\n", data1.floatData);
// Modifying the union's content by assigning a character
data1.charData = 'A';
printf("Character Data: %c\n", data1.charData);

// Displaying information from the union after modifications


printf("After Modifications (Union):\n");
printf("Integer Data: %d\n", data1.integerData);
printf("Float Data: %.2f\n", data1.floatData);
printf("Character Data: %c\n", data1.charData);

return 0;
}

Structure Pointer in C
A structure pointer is defined as the pointer which points to the address of the memory block that
stores a structure known as the structure pointer. Complex data structures like Linked lists, trees,
graphs, etc. are created with the help of structure pointers. The structure pointer tells the address
of a structure in memory by pointing the variable to the structure variable.
Example:
// C program to demonstrate structure pointer
#include <stdio.h>
struct point {
int value;
};

int main()
{
struct point s;
// Initialization of the structure pointer
struct point* ptr = &s;

return 0;
}
In the above code s is an instance of struct point and ptr is the struct pointer because it is storing
the address of struct point.

Accessing the Structure Member with the Help of Pointers


There are two ways to access the members of the structure with the help of a structure pointer:
1. With the help of (*) asterisk or indirection operator and (.) dot operator.
2. With the help of ( -> ) Arrow operator.
Below is the program to access the structure members using the structure pointer with the help of
the dot operator.

// C Program to demonstrate Structure pointer


#include <stdio.h>
#include <string.h>

struct Student {
int roll_no;
char name[30];
char branch[40];
int batch;
};

int main()
{
struct Student s1;
struct Student* ptr = &s1;

s1.roll_no = 27;
strcpy(s1.name, "Kamlesh Joshi");
strcpy(s1.branch, "Computer Science And Engineering");
s1.batch = 2019;

printf("Roll Number: %d\n", (*ptr).roll_no);


printf("Name: %s\n", (*ptr).name);
printf("Branch: %s\n", (*ptr).branch);
printf("Batch: %d", (*ptr).batch);

return 0;
}
Output:
1

Below is the program to access the structure members using the structure pointer with the help of
the Arrow operator. In this program, we have created a Structure Student containing structure
variable s. The Structure Student has roll_no, name, branch, and batch.

// C Program to demonstrate Structure pointer


#include <stdio.h>
#include <string.h>

// Creating Structure Student


struct Student {
int roll_no;
char name[30];
char branch[40];
int batch;
};

// variable of structure with pointer defined


struct Student s, *ptr;

int main()
{

ptr = &s;
// Taking inputs
printf("Enter the Roll Number of Student\n");
scanf("%d", &ptr->roll_no);
printf("Enter Name of Student\n");
scanf("%s", &ptr->name);
printf("Enter Branch of Student\n");
scanf("%s", &ptr->branch);
printf("Enter batch of Student\n");
scanf("%d", &ptr->batch);

// Displaying details of the student


printf("\nStudent details are: \n");

printf("Roll No: %d\n", ptr->roll_no);


printf("Name: %s\n", ptr->name);
printf("Branch: %s\n", ptr->branch);
printf("Batch: %d\n", ptr->batch);

return 0;
}

Output:
Enter the Roll Number of Student
27
Enter Name of Student
Kamlesh_Joshi
Enter Branch of Student
Computer_Science_And_Engineering
Enter batch of Student
2019
Student details are:
Roll No: 27
Name: Kamlesh_Joshi
Branch: Computer_Science_And_Engineering
Batch: 2019
Dynamic memory allocation of structs
we recommend you to check C dynamic memory allocation. Sometimes, the number of struct
variables you declared may be insufficient. You may need to allocate memory during run-time.
Here's how you can achieve this in C programming.

Example: Dynamic memory allocation of structs


#include <stdio.h>
#include <stdlib.h>
struct person {
int age;
float weight;
char name[30];
};

int main()
{
struct person *ptr;
int i, n;

printf("Enter the number of persons: ");


scanf("%d", &n);

// allocating memory for n numbers of struct person


ptr = (struct person*) malloc(n * sizeof(struct person));

for(i = 0; i < n; ++i)


{
printf("Enter first name and age respectively: ");
// To access members of 1st struct person,
// ptr->name and ptr->age is used

// To access members of 2nd struct person,


// (ptr+1)->name and (ptr+1)->age is used
scanf("%s %d", (ptr+i)->name, &(ptr+i)->age);
}

printf("Displaying Information:\n");
for(i = 0; i < n; ++i)
printf("Name: %s\tAge: %d\n", (ptr+i)->name, (ptr+i)->age);

return 0;
}

When you run the program, the output will be:


Enter the number of persons: 2
Enter first name and age respectively: Harry 24
Enter first name and age respectively: Gary 32
Displaying Information:
Name: Harry Age: 24
Name: Gary Age: 32

In the above example, n number of struct variables are created where n is entered by the user.
To allocate the memory for n number of struct person, we used,
ptr = (struct person*) malloc(n * sizeof(struct person));
Then, we used the ptr pointer to access elements of person.
Introduction to preprocessor directives
preprocessor directives
We can consider a preprocessor as a compilation process, which runs when the developer runs
the program. It is a pre-process of execution of a program using c/c++ language. To initialize a
process of preprocessor commands, it's mandated to define with a hash symbol (#). It can
preferably be the non-blank character, and for better readability, a preprocessor directive should
start in the first column.

Want a Top Software Development Job? Start Here!


Full Stack Development-MEANEXPLORE PROGRAMWant a Top Software Development Job?
Start Here!
List of Preprocessor Directives
To execute a preprocessor program on a certain statement, some of the preprocessor directives
types are:

#define: It substitutes a preprocessor using macro.


#include: It helps to insert a certain header from another file.
#undef: It undefines a certain preprocessor macro.
#ifdef: It returns true if a certain macro is defined.
#ifndef: It returns true if a certain macro is not defined.
#if, #elif, #else, and #endif: It tests the program using a certain condition; these directives can be
nested too.
#line: It handles the line numbers on the errors and warnings. It can be used to change the line
number and source files while generating output during compile time.
#error and #warning: It can be used for generating errors and warnings.
#error can be performed to stop compilation.
#warning is performed to continue compilation with messages in the console window.
#region and #endregion: To define the sections of the code to make them more understandable
and readable, we can use the region using expansion and collapse features.
Process Flow of Preprocessor Directives
A developer writes a C program-> and the program checks if there are any preprocessor
directives available.
If available, it will perform the action event of pre-processor and the compiler will generate the
object code. The code will then be executed by the linker.
In case no preprocessor directives are available, it will go to the compiler. The compiler will then
generate the object code followed by execution of the code by linker.
Here in the article, we will look at the various examples of preprocessor directives.

Want a Top Software Development Job? Start Here!


Full Stack Development-MEANEXPLORE PROGRAMWant a Top Software Development Job?
Start Here!
Four Major Types of Preprocessor Directives
1. Macro Expansion
In Macro expansion, we can specify two types of Macros with arguments:

We can also pass arguments to macros; it can be described with arguments that perform similarly
as functions.

Syntax:
#define name substitute text

Where,

name: Here, we can define the micro template.


replacement text : we can define it as the macro expansion.
To write a macro name, we need to use capital letters.
For better readability, we can define suitable names on certain macros.
To modify program: We can change only the macro and it can reflect on the program. Hence we
do not need to change it every time.
Example: Basic Macro
#define PrintLOWER 50

void main()

int j;

for (j=1;i<=PrintLOWER; j++)

printf("\n%d", j);

Example: Macros With Certain Arguments


#define AREA(a) (5.18 * a * a)

void main()

float r = 3.5, x;

x = AREA (r);
printf ("\n Area of circle = %f", x);

Types of Predefined Macros


___TIME___ defines the current time using a character literal in “HH:MM: SS” format.
___STDC___ specifies as 1 when the compiler complies with the ANSI standard.
___TIMESTAMP___ specifies the timestamp “DDD MM YYYY Date HH:MM: SS”. It is used
to define the date and time of the latest modification of the present source file.
___LINE___ consists of a present line number with a decimal constant.
___FILE___ includes the current filename using a string literal.
___DATE___ shows the present date with a character literal in the “MMM DD YYYY” format.
Want a Top Software Development Job? Start Here!
Full Stack Development-MEANEXPLORE PROGRAMWant a Top Software Development Job?
Start Here!
2. File Inclusion
For file inclusion, we can use the #include.

Syntax:
#include TypeYourfilename

We can replace the content that is comprised in the filename at the point where a certain directive
is written.
We can use a file inclusive directive and include the header files in the programs.
We can integrate function declaration, macros, and declarations of the external variables in the
top header file rather than repeating each logic in the program.
The stdio.h header file includes the function declarations and can provide the details about the
input and output.
Example of the file inclusion statement:
i) #include “DefineYourfile-name”: In this example, we can search a file within the current
working directory through easy search.
ii) #include <DefineYourfile-name>: In this example, we can define a certain directory, and we
search a file within it.
3. Conditional Compilation
We can use conditional compilation on a certain logic where we need to define a condition
logics.
It utilizes directives like #if, #elif, #else, and #endif.
Syntax:
#if TESTYourCondition <= 8

statement 1;

statement 2;

statement 3;

statement 4;

#else

statement 5;

statement 6;

statement 7;

#endif
Want a Top Software Development Job? Start Here!
Full Stack Development-MEANEXPLORE PROGRAMWant a Top Software Development Job?
Start Here!
4. Miscellaneous Directives
There are two miscellaneous directives apart from the above directives that are not commonly
used.

#undef: We can use this directive with the #define directive. It is used to undefine a specified
macro.
#pragma: We can use this directive on a certain level where we need to define turn-on or off
specific features. We can use these types of directives for the compiler-specific, which has a
certain range as complier to the compiler. Example of #pragma directives are discussed below:
#pragma startup and #pragma exit: These directives push to indicate the functions that are
required to run before the program as a startup (before the control moves to main()) and before
program exit (only before the control returns from main()).
Code Example: #pragma Directives
#include <yourincludefile>

using namespace Emp;

void Empfun1();

void Empfun2();

#pragma startup Empfun1

#pragma exit Empfun2

void Empfun1()
{

cout << "Print the logic on Empfun1()\n";

void Empfun2()

cout << "Print the logic on Empfun2()\n";

int main()

void Empfun1();

void Empfun2();

cout << "Print main output ()\n";

return 0;

}
Output:
Print the logic on Empfun1()

Print main output ()

Print the logic on Empfun2()

Want a Top Software Development Job? Start Here!


Full Stack Development-MEANEXPLORE PROGRAMWant a Top Software Development Job?
Start Here!
#pragma warn Directive:
Pragma directive is the certain directive that we can utilize to make it turn off and on to enable
certain features. Pragma specifies the range from one compiler to another. Microsoft C compiler
provides the pragmas that provide the listing and placing ways to give the comments in the
object file that is generated by the compiler. Prgama has its custom-specific implementation rules
directives that can be defined as per the certain scenario.

pragma startup and #pragma exit: These pragma directives are defined as the certain functions
that can be used to determine to run before program startup that can be specified before to main()
and before program exit can be applied before the control returns from main().

Example:
#include<stdio.h>

void testFun1(();

void testFun2();

#pragma startup testFun1

#pragma exit testFun2


void testFun1()

printf("It is Inside the testFun1()\n");

void testFun2()

printf("It is Inside the func2()\n");

int main()

printf("It is Inside the function of main()\n");

return 0;

Output
It is Inside the testFun1()

It is Inside the function of main()

It is Inside the func2()


Let's delve into the realm of preprocessor directives in the context of C programming.
In C programming, the preprocessor is a powerful tool that plays a crucial role in the compilation
process. It operates on the source code before the actual compilation begins, and one of its
primary components is preprocessor directives. These directives are special commands that start
with a hash symbol (#) and provide instructions to the preprocessor.

1. Include Directive:
One of the most commonly used preprocessor directives is `#include`. It allows us to include
header files in our program, making functions and declarations from those files available for use.
For instance:

#include <stdio.h>

2. Define Directive:
The `#define` directive is used for creating macros, which are symbolic names representing a
sequence of characters. This aids in code readability and maintenance. For example:

#define PI 3.14

3. Conditional Compilation:
Directives like `#ifdef`, `#ifndef`, `#if`, `#else`, and `#endif` enable conditional compilation.
This allows parts of the code to be included or excluded based on certain conditions, enhancing
code flexibility.

#ifdef DEBUG
// Debugging code
#else
// Release code
#endif

4. Macro Functions:
With `#define`, you can create macro functions to simplify repetitive tasks. These are
essentially code snippets that can be reused throughout your program.

#define SQUARE(x) x*x

5. Stringizing Operator (#):


The `#` operator, when used within a macro, turns a macro parameter into a string constant.
This is particularly useful in debugging and error messages.

#define STRINGIZE(x) #x

6. Token Pasting Operator (##):


The `##` operator concatenates two tokens, which can be handy in creating more complex
macros.

#define CONCAT(x, y) x##y

Understanding and utilizing these preprocessor directives can significantly enhance the
efficiency and flexibility of your C programs. They offer a powerful mechanism for code
organization, reusability, and conditional compilation.
Let's delve into multiple examples for each of the preprocessor directives we discussed.
1. Include Directive:
- Single include:
#include <stdio.h>

- Multiple includes:
#include <stdio.h>
#include <stdlib.h>

2. Define Directive:
- Simple constant:
#define PI 3.14

- Macro with parameters:


#define SQUARE(x) x*x

3. Conditional Compilation:
- Basic `#ifdef` and `#endif`:
#ifdef DEBUG
// Debugging code
#endif

- `#if`, `#else`, and `#endif`:


#if defined(DEBUG) && (VERSION == 2)
// Debugging code for version 2
#else
// Release code or other versions
#endif
4. Macro Functions:
- Simple arithmetic operation:
#define ADD(x, y) (x + y)

- More complex operation:


#define MAXIMUM(a, b) ((a > b) ? a : b)

5. Stringizing Operator (#):


- Converting macro parameter to a string:
#define STRINGIZE(x) #x

- Combining strings:
#define CONCAT_STR(a, b) a##b

6. Token Pasting Operator (##):


- Combining tokens:
#define CONCAT_TOKENS(x, y) x##y

- Creating variable names dynamically:


#define VAR_NAME(prefix, suffix) prefix##_##suffix

These examples showcase the versatility of preprocessor directives. They can significantly
enhance the readability, maintainability, and flexibility of your C code.
Macro: A macro is a fragment of code that has been given a name. These named fragments,
known as macros, are created using the `#define` preprocessor directive. Macros are essentially a
form of symbolic representation that allows you to define constants, functions, or code snippets
for reuse throughout your program.
Let's explore the different aspects of macros through examples:

1. Simple Constant Macro:


#define PI 3.14

Here, `PI` is a macro representing the constant value 3.14. When the preprocessor encounters
`PI` in the code, it replaces it with the actual value before compilation.

2. Macro Functions:
#define SQUARE(x) x*x

This macro defines a function-like macro `SQUARE` that squares its argument. For instance,
`SQUARE(5)` would be replaced by `5*5` during preprocessing.

3. Parameterized Macros:
#define MAX(a, b) ((a > b) ? a : b)

Here, `MAX` is a macro taking two parameters and returning the maximum of the two. It's a
convenient way to create compact and readable expressions.

4. Stringizing Operator (#):


#define STRINGIZE(x) #x
The stringizing operator turns a macro parameter into a string constant. For example,
`STRINGIZE(Hello)` would be replaced by `"Hello"`.

5. Token Pasting Operator (##):


#define CONCAT(x, y) x##y

The token pasting operator concatenates two tokens into a single token. For instance,
`CONCAT(var, 1)` would be replaced by `var1`.

6. Conditional Compilation with Macros:


#ifdef DEBUG
// Debugging code
#endif

Macros are often used for conditional compilation, allowing you to include or exclude code
based on certain conditions.

In summary, macros in C are a powerful tool for code abstraction, allowing you to create
reusable code snippets and improve code maintainability. However, it's important to use them
judiciously, as overuse can lead to code that is difficult to understand.

Addition program using macros


Let's create a simple addition program using macros to showcase how they can be utilized for
basic operations.
#include <stdio.h>

// Macro to perform addition


#define ADDITION(x, y) (x + y)
int main() {
// Variables
int num1, num2, result;

// Input
printf("Enter the first number: ");
scanf("%d", &num1);

printf("Enter the second number: ");


scanf("%d", &num2);

// Addition using the macro


result = ADDITION(num1, num2);

// Output
printf("The sum of %d and %d is: %d\n", num1, num2, result);

return 0;
}

In this example, the `ADDITION` macro takes two parameters (`x` and `y`) and returns their
sum. The program prompts the user to input two numbers, performs the addition using the
macro, and then prints the result.

Here's a breakdown of how the macro is used in the code:


result = ADDITION(num1, num2);

During the preprocessing stage, this line would be replaced with:


result = (num1 + num2);

This demonstrates how macros can be employed for simple arithmetic operations, providing a
concise and readable way to express the addition operation.

if statement using macros.


Let's create a simple if statement using macros. Macros can be employed to improve code
readability, especially in scenarios where conditional compilation or code variations are
necessary.

#include <stdio.h>

// Macro to check if a number is even


#define IS_EVEN(num) (num % 2 == 0)

int main()
{
// Variable
int number;

// Input
printf("Enter a number: ");
scanf("%d", &number);

// If statement using the macro


if (IS_EVEN(number))
{
printf("%d is an even number.\n", number);
} else
{
printf("%d is an odd number.\n", number);
}

return 0;
}

In this example, the `IS_EVEN` macro takes a single parameter (`num`) and returns a boolean
result indicating whether the number is even. The macro is then used in an if statement to
determine if the entered number is even or odd.

Here's a breakdown of how the macro is used in the code:


if (IS_EVEN(number))
{
// Code for even number
}
else
{
// Code for odd number
}

During the preprocessing stage, this would be replaced with:


if (number % 2 == 0) {
// Code for even number
} else {
// Code for odd number
}
This showcases how macros can be employed to encapsulate logic and enhance code readability,
especially when dealing with conditional statements.

You might also like