Unit 4
Unit 4
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.
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.
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);
free(ptr);
return 0;
}
Output
Enter size: 2
Addresses of previously allocated memory:
26855472
26855476
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:
#include <stdio.h>
#include <stdlib.h>
int main()
{
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()
{
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()
{
return 0;
}
Output
Enter number of elements: 5
Memory successfully allocated using malloc.
Malloc 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'.
#include <stdio.h>
#include <stdlib.h>
int main()
{
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,
#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:
if (dynamicArray == NULL) {
printf("Memory allocation failed\n");
return 1; // Exit the program with an error code
}
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:
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:
#include <stdio.h>
#include <string.h>
int main() {
// Example of using a structure
struct Student student1;
strcpy(student1.name, "John Doe");
student1.age = 20;
student1.marks = 85.5;
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.
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;
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.
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);
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.
int main()
{
struct person *ptr;
int i, n;
printf("Displaying Information:\n");
for(i = 0; i < n; ++i)
printf("Name: %s\tAge: %d\n", (ptr+i)->name, (ptr+i)->age);
return 0;
}
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.
We can also pass arguments to macros; it can be described with arguments that perform similarly
as functions.
Syntax:
#define name substitute text
Where,
void main()
int j;
printf("\n%d", j);
void main()
float r = 3.5, x;
x = AREA (r);
printf ("\n Area of circle = %f", x);
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>
void Empfun1();
void Empfun2();
void Empfun1()
{
void Empfun2()
int main()
void Empfun1();
void Empfun2();
return 0;
}
Output:
Print the logic on Empfun1()
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();
void testFun2()
int main()
return 0;
Output
It is Inside the testFun1()
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 STRINGIZE(x) #x
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
3. Conditional Compilation:
- Basic `#ifdef` and `#endif`:
#ifdef DEBUG
// Debugging code
#endif
- Combining strings:
#define CONCAT_STR(a, b) a##b
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:
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.
The token pasting operator concatenates two tokens into a single token. For instance,
`CONCAT(var, 1)` would be replaced by `var1`.
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.
// Input
printf("Enter the first number: ");
scanf("%d", &num1);
// 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.
This demonstrates how macros can be employed for simple arithmetic operations, providing a
concise and readable way to express the addition operation.
#include <stdio.h>
int main()
{
// Variable
int number;
// Input
printf("Enter a number: ");
scanf("%d", &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.