0% found this document useful (0 votes)
5 views36 pages

Unit IV - Functions

The document discusses the importance of functions in programming, particularly in C, highlighting their role in managing large programs by breaking them into manageable modules. It explains the types of functions, including library functions and user-defined functions, and details their advantages and disadvantages. Additionally, it covers the elements of function declaration, calling, and definition, along with various categories of functions based on parameters and return values.

Uploaded by

Vinay Vinnu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views36 pages

Unit IV - Functions

The document discusses the importance of functions in programming, particularly in C, highlighting their role in managing large programs by breaking them into manageable modules. It explains the types of functions, including library functions and user-defined functions, and details their advantages and disadvantages. Additionally, it covers the elements of function declaration, calling, and definition, along with various categories of functions based on parameters and return values.

Uploaded by

Vinay Vinnu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 36

FUNCTIONS

Designing Structured Programs:

If the program is very big, there are too many disadvantages,

 It is very difficult for the programmer to write a large program.


 Very difficult to identify the logical errors and correct.
 Very difficult to read and understand.
 Large programs are may cause errors.

These disadvantages can be overcome using functions.

To design lengthy programs, first we must understand the problem and then it should be
divided into different parts/sections. Each part is called a "Module".

 The process of dividing a problem into different parts is called as “Top-Down


Design Approach”.
 A module which is calling different sub module is called as "Calling Module".
 A module which is called by another module is called "Called Module".
Function:

"A function is a self contained block of statements that perform specific task".

 Every C program consists of one or more functions. One of these function must
be called main( ).
 Execution of the program will always begin by carrying out the instructions in
main( ).
 Additional functions will be sub programs to main( ) , and perhaps to one another.
 C language provides an approach in which you need to declare and define a group
of statements once and that can be called and used whenever required. This saves
both time and space.
 Once the function has carried out its intended action, control will be returned to
the point from which the function was accessed.

The functions can be classified into two categories as shown in fig:

Library (or) Built-in functions:

The C language supports lots of standard predefined functions known as library


functions. These functions which are part of the C compiler that have been written for
general purpose. They are also called built – in functions.

For example,

 The function sqrt ( ) is used to finds the square root of a given number.
 The function scanf ( ) is used to accept the data from the keyboard.
 The function printf ( ) is used to print result on to the display device.
 The function pow ( ) is used to find power of variable.
You just need to include appropriate header files to use these functions. These are
already declared and defined in C libraries.

Advantages:

 The programmer’s job is made easier because the functions are already available.
 The library functions can be used whenever required.

Disadvantages:

 Since the standard library functions are limited, programmer cannot completely
rely on these library functions. The programmer has to write his own programs.

These disadvantages of standard library functions can be overcome using user -


defined functions.

User defined functions:

These functions which are written by the programmer or user to do specific tasks
are called user defined function ( UDFs ) .

Depending upon the complexity and requirement of the program, you can create
as many user-defined functions as you want.

Advantages:

 The program will be easier to understand, maintain and debug.


 These functions are made for code reusability and for saving time and space.
 A large program can be divided into smaller modules. Hence, a large program can be
divided among many programmers.
 A function can be shared by many programmers.
 Avoids the repetition of statements.
Elements of user defined functions:

To create user defined functions we have to write three elements in a program

1. Function declaration/ function prototype


2. Function call.
3. Function definition.

FUNCTION DECLARATION/ FUNCTION PROTOTYPE:

Just like variables, a function must be declared at the beginning of a program before they
are defined and end with semicolon. Function declaration is also called function
prototype.

The function declaration must match with the function header in the function declaration.

Syntax:

return type function name (type 1 arg 1, type 2 arg 2, type 3 arg 3, …. type n arg n );

here, return type represents the datatype of the item that is returned by the function,
function name represents the name of the function.
type 1, type 2,…..type n represent the data types of the arguments arg 1, arg 2 ,
….. arg n.

NOTE: if no return type has been specified, in such case, the default value that the
function expected to return will be of type int.

Ex: void add ( );


int add (int, int);
int add( ) ;
FUNCTION CALL:

To execute a function, it must be called from another function. This is called as


function call. In general, A function call is nothing but invoking a function at the required
place in the program.

Syntax:

function_name (List of Actual Arguments);

Ex: add( );

add(a, b);

c = add();

NOTE: when a function is invoked, the parameters which are used in a function
call are called actual parameters.

FUNCTION DEFINITION:

It is an independent module which contains statements that perform specific operation.

Syntax:
return type function_name (list of formal parameters)
{
Local variable declaration
Statements;
_____
_____
_____
return (value) ;
}

Here,

return type: can be int , float , double, void etc. this is the type of the value that the
function is expected to return. If the function is not returning any value, then need
to specify the return type as void.
function_name: The function name can be any valid identifier. This function name
should match with function name in function declaration.

List of parameters:

Parameters are list of variables. All the variables should be separately declared
and each declaration should be separated by comma. These variables accept the
values when the function is invoked. These variables are called formal
parameters.

return :

Using this statement, the function returns the evaluated result. If a function does
not return any value, the return statement can be omitted.

 A function may not send the value or may send the value to the calling function. This
is possible only using the return statement.

Syntax:

return (value); or return;

 We can write more than one return statement using if-else statement.
 This statement will return the control back to the calling function.

Examples:

Write a C program to find the factorial of a number using functions.

#include<stdio.h>
#include<conio.h>
void factorial ( int ) ; /*FUNCTION DECLARATION*/
void main ( )
{
int n ;
clrscr ( ) ;
printf (" \n Enter integer value to find factorial: " ) ;
scanf ( " %d " , &n ) ;
factorial ( n ) ; /*FUNCTION CALL*/
getch ( ) ;
}
void factorial ( int n) /*FUNCTION DEFINITION*/
{
int i , fact = 1;
for ( i = 0; i <= n; i ++)
{
fact = fact * i ;
}
printf (“ \n factorial of %d is = %d ” , n , fact ) ;
}

OUTPUT:

Enter integer value to find factorial: 5


factorial of 5 is = 120

Write a C program to perform addition of two numbers using functions.

#include<stdio.h>
#include<conio.h>
void add ( int , int ) ; /*FUNCTION DECLARATION*/
void main ( )
{
int a ,b ;
clrscr ( ) ;
printf (" \n Enter 2 integers: ") ;
scanf ( " %d %d " , &a , &b ) ;
add ( a , b ) ; /*FUNCTION CALL*/
getch ( ) ;
}
void add ( int x, int y) /*FUNCTION DEFINITION*/
{
printf (“ \n Sum = %d ” , x+y ) ;
}
OUTPUT:

Enter 2 integers: 10 20
Sum = 30

Write a C program to find maxim of two numbers using functions.

#include<stdio.h>
#include<conio.h>
void maximum ( int , int ) ; /*FUNCTION DECLARATION*/
void main ( )
{
int m ,n , res ;
clrscr ( ) ;
printf (" \n Enter 2 integers: ") ;
scanf ( " %d %d " , &m , &n ) ;
res = maximum ( m , n ) ; /*FUNCTION CALL*/
printf (“ \n maximum number is = %d ” , res ) ;
getch ( ) ;
}
void maximum ( int x, int y) /*FUNCTION DEFINITION*/
{
if ( m > n)
return m ;
else
return n ;
}

OUTPUT:

Enter 2 integers: 10 20
maximum number is = 20
CATEGORIES OF FUNCTION – FUNCTION CALL:

Based on the parameters and return value, the functions are categorized as follows:

 Function without parameters and without return value


 Function with parameters without return value
 Function without parameters and with return value
 Function with parameters and with return value

FUNCTION WITHOUT ARGUMENTS AND WITHOUT RETURN VALUE :

In this category, there is no data transfer between the calling function and called
function. But, there is flow of control from calling function to the called function and
back as shown in fig.

Generally, the calling function will not sent any values to the called function.
Similarly, the called function will not return any value to the calling function.
Example :
/*Program to illustrate function without arguments and without return value*/
#include<stdio.h>
#include<conio.h>
void add ( ); /*FUNCTION DECLARATION*/
void main( )
{
clrscr ( ) ;
add ( ) ; /*FUNCTION CALL*/
}
void add ( ) /*FUNCTION DEFINITION*/
{
int a = 10 , b = 20 ;
printf (" \n Sum = %d " , a+b ) ;
getch ( ) ;
}
OUTPUT:
Sum = 30
FUNCTION WITH PARAMETERS WITHOUT RETURN VALUE

In this category, there is data transfer from the calling function to the called
function using parameters. But, there is flow of control from calling function to the called
function with parameters and back without return value as shown in fig.

Generally, Calling Function will send the values to the called function. The values
will be processed to the called function, but no return value will be sent back to the
calling function.

Example:

/*program to illustrate function with arguments and without return value*/


#include<stdio.h>
#include<conio.h>
void add ( int , int ) ; /*FUNCTION DECLARATION*/
void main ( )
{
int a ,b ;
clrscr ( ) ;
printf (" \n Enter 2 integers: ") ;
scanf ( " %d %d " , &a , &b ) ;
add ( a , b ) ; /*FUNCTION CALL*/
getch ( ) ;
}
void add ( int x, int y) /*FUNCTION DEFINITION*/
{
printf (“ \n Sum = %d ” , x+y ) ;
}

OUTPUT:

Enter 2 integers: 10 20
Sum = 30

FUNCTION WITHOUT PARAMETERS AND WITH RETURN VALUE

In this category, there is no data transfer from the calling function to the called
function. But, there is data transfer from called function to the calling function.

Generally, In this the calling function will not sent any values to the called
function. But the called function will send back a value to the called function.

/*program to illustrate function without arguments and with return value*/

#include<stdio.h>
#include<conio.h>
int add ( ) ; /*FUNCTION DECLARATION*/
void main ( )
{
int c;
clrscr ( ) ;
c=add ( ) ; /*FUNCTION CALL*/
printf (" \n Sum = %d " , c ) ;
getch ( ) ;
}
int add ( ) /*FUNCTION DEFINITION*/
{
int x , y , z ;
printf ("\n Enter 2 integers: ");
scanf (" %d %d " , &x , &y) ;
z=x+y;
return z;
}

OUTPUT:
Enter 2 integers: 10 20
Sum = 30

FUNCTION WITH PARAMETERS AND WITH RETURN VALUE

In this category, there is data transfer between the calling function and the called
function. when parameters are passed, the called function can receive values from calling
function. when the function returns a value, the calling function can receive a value from
the called function. as shown in fig:
/*program to illustrate function without arguments and without return value*/
#include<stdio.h>
#include<conio.h>
int add (int , int) ; /*FUNCTION DECLARATION*/
void main ( )
{
int c;
clrscr ( ) ;
printf ( “ \n Enter 2 Numbers: ” ) ;
scanf ( “ %d %d ” ,&a , &b ) ;
c = add ( a , b ) ; /*FUNCTION CALL*/
printf ( " \n Sum = %d " , c ) ;
getch ( ) ;
}
int add (int x, int y) /*FUNCTION DEFINITION*/
{
return (x + y) ;
}

OUTPUT:

Enter 2 Numbers: 10 20
Sum = 30

INTER FUNCTION COMMUNICATION:

The data flow between the calling function and called function is divided into 3
categories.
1. Downward flow
2. Upward flow
3. Bidirectional flow
1. Downward flow:

 In the downward flow, data flows from the calling function to the called function.
 Any changes made to the called function will not take effect the calling function.

Ex:-

 Functions with Arguments and without return value mechanism


 Call by value mechanism

2. UPWARD FLOW:

 In the upward data flow the data flows from the called function to the calling
function.
 Using the return statement we can send the data back to the calling function.
 If we want to return more than one value we can use the call by ref mechanism.

Ex: Functions without Arguments and with return value mechanism

3. BI DIRECTIONAL FLOW:

 In this category the data flows in both the directions i.e., from calling function to
called function and vice-versa.

Ex:

 Functions with Arguments and with return value mechanism


 Call by ref mechanism
Types of parameters:

There are two types of parameters, they are:


1. Actual parameters
2. Formal parameters

Now, let see the difference between actual parameters and formal parameters:

Actual parameters Formal parameters


Actual parameters are used in calling 1 Formal parameters are used in called
function. function
Ex: c = sum (a,b); Ex: int sum(int m, int n)
Here, a & b are called actual Here, m & n are called formal
parameters Parameters
Actual parameters can be constants, 2 Formal parameters should be only
variables or expressions variables. Constants and expressions
Ex: c = sum( a+4,b); are not allowed.
c = sum ( 5, 6); Ex: int sum( int m,int n) // allow
int sum( int m+n ,int n) //wrong
int sum( int m, 10) // wrong
Actual parameters can sends values 3 Formal parameters receive values
to the formal parameters from the actual parameters
Ex: c = sum( 4,5); Ex: int sum ( int m, int n)
Here, m will have the value 4
n will have the value 5
Addresses of actual parameters can 4 If formal parameters contain
be sent to formal parameters. addresses, they should be declared as
pointers.
PASSING PARAMETERS TO FUNCTIONS

There are 2 ways in which we can pass arguments or parameters to a function, they are

1. Call by value (or) pass by value


2. Call by reference ( or) pass by reference

Call by value (or) pass by value

When a function is called with actual parameters, the values of actual parameters
are copied into formal parameters. If the values of the formal parameters changes in the
function, the values of the actual parameters are not changed. This way of passing
parameters is called pass by value or call by value.

Ex: swapping two numbers using functions


/*program to illustrate about call by value*/
#include<stdio.h>
#include<conio.h>
void Swap(int x, int y); // function declaration
void main ( )
{
int a = 10 , b = 20 ;
clrscr ( ) ;
printf ( " \n\n In main before swap a = %d , b = %d " , a , b ) ;
Swap ( a , b ) ; // function calling
printf ( " \n\n In main After swap a = %d , b = %d " , a , b ) ;
getch ( ) ;
}
void Swap(int x, int y) // function definition
{
int temp;
temp = x ;
x=y;
y = temp ;
printf ( " \n\n In SWAP FUN a = %d , b = %d " , x , y ) ;
}
OUTPUT:
In Main before swap a = 10, b = 20
In Main After swap a = 10, b = 20
In SWAP FUN b = 20, b = 10

In the above program observe that a & b values are same before and after swap,
but in swap function x and y (those carries the values of a=10 and b=20) are swapped.

CALL BY REFERENCE (OR) PASS BY REFERENCE

In pass by reference, a function is called with address of actual parameters and


formal parameters receive the addresses of actual parameters. If any variable contains an
address, it is called a pointer variable. Means the formal parameters will be the pointers
to the actual arguments. Any changes made to the formal parameters, will affect to the
actual parameters using pointers. This way of passing parameters is called pass by
reference or call by reference.

Ex:- Program to swap a , b values

/*PROGRAM TO ILLUSTRATE ABOUT CALL BY REFERENCE*/

#include<stdio.h>
#include<conio.h>
void Swap(int *,int *); // function declaration
void main( )
{
int a = 10 , b = 20 ;
clrscr ( );
printf (" \n\n In main, the values before swap: a = %d b = %d " , a , b ) ;
Swap (&a , &b); // function calling
printf (" \n\n In main, the values after swap: a = %d b = %d " , a , b ) ;
getch ( ) ;
}
void Swap ( int *x , int *y) // function definition
{
int temp ;
temp = *x;
*x = *y;
*y = temp;
printf (" \n The values after swap in swap function: *x = %d *y = %d ",*x , *y );
}
OUTPUT:
In main, the values before swap: a = 10 b = 20
The values after swap in swap function: *x = 20 *y = 20
In main, the values after swap: a = 20 b = 10

PASSING ARRAYS TO FUNCTIONS:

We can pass arrays to functions in two ways.


1. Passing individual elements
2. Passing a whole array.

Passing individual elements:

 Just like normal variables we can pass individual elements of an array to a function
 We can pass either the values or the address of an array to a function.
 To pass a value to a function, give the array name along with its index in the function
call.
 We can pass the address of individual array elements to a function

/*PROGRAM TO SEND AN INDIVIDUAL ELEMENT TO A FUNCTION*/


#include<stdio.h>
#include<conio.h>
void fun (int ) ; // function declaration
void main ( )
{
int a[5] , i ;
clrscr ( ) ;
for ( i = 0 ; i < 5 ; i ++)
{
printf ( " Enter a[%d] = " , i ) ;
scanf ( " %d " , &a[i] ) ;
}
for ( i = 0 ; i < 5 ; i ++)
{
fun ( a [ i ] ) ; // function calling
}
getch ( ) ;
}

void fun (int x) // function definition


{
printf (" \t %d " , x ) ;
}

OUTPUT:

Enter a[0] = 1
Enter a[1] = 2
Enter a[2] = 3
Enter a[3] = 4
Enter a[4] = 5
1 2 3 4 5

/* PASSING ADDRESS OF INDIVIDUAL ARRAY ELEMENT TO FUN*/


#include<stdio.h>
#include<conio.h>

void fun (int *) ; // function declaration


void main ( )
{
int a[5] = { 1 , 2 , 3 , 4 , 5 } , i ;
clrscr ( ) ;
for ( i = 0 ; i < 5 ; i ++)
{
fun (& a [ i ] ) ; // function calling
}
getch ( ) ;
}
void fun(int *x) // function definition
{
printf ( " \t %d " , *x ) ;
}

OUTPUT:

1 2 3 4 5

Passing a whole array:

One-Dimension Array passing:


 The function prototype must show that the argument is an array.
 The function must be called by passing array name and size.
 To pass a 1-Dim array we have to specify the array name without subscript and with
size as arguments.
 In function definition, the formal parameters must be an array type and no need to
specify the size inside the subscript.

/* PASSING A WHOLE ARRAY A TO A FUNCTION*/


#include<stdio.h>
#include<conio.h>
void fun ( int [ ] , int ) ; // function declaration
void main ( )
{
int a[ ] ={ 1 , 2 , 3 , 4 , 5 } , i ;
clrscr ( ) ;
fun ( a , 5 ) ;
getch ( ) ;
}
void fun ( int x[ ] , int n) //function definition
{
int j ;
for ( j = 0 ; j < n ; j ++)
printf ( " \t a [ %d ] = %d " , j , x [ j ] ) ;
}

OUTPUT:

A[0] = 1 a[1] = 2 a[2] = 3 a[3] = 4 a[4] = 5

 In C, the name of an array represents the address of its first element.


 By passing an array to a function the address of the array will be sent to the function.
 The formal parameters refer to the actual array stored in the memory.
 Any changes made in the formal arguments will be reflected in the original array.

/* PASSING A WHOLE ARRAY A TO A FUNCTION*/


#include<stdio.h>
#include<conio.h>
void fun ( int [ ] , int ) ; // function declaration
void main ( )
{
int a [ ] = { 1 , 2 , 3 , 4 , 5 } , i ;
clrscr ( ) ;
fun ( a , 5 ) ; // function call
for ( i = 0 ; i < 5 ; i ++)
printf ( " \n NEW ARRAY \t a [ %d ] = %d " , i , a [ i ] ) ;
getch ( ) ;
}
void fun ( int x[ ] , int n) // function definition
{
int j ;
for ( j = 0 ; j < n ; j ++)
{
printf (" \t a[ %d ] = %d " , j , x[ j ] ) ;
x[j]+=9;
}
}

OUTPUT:

A[0] = 1 a[1] = 2 a[2] = 3 a[3] = 4 a[4] = 5

NEW ARRAY a [0] =10


NEW ARRAY a [1] =11
NEW ARRAY a [2] =12
NEW ARRAY a [3] =13
NEW ARRAY a [4] =14

Two Dimension Array passing:

 To pass a two dimensional array to a function, we have to specify the array name and
the two dim in the function call.
 The function must be called by passing array name and the size of rows and columns.
 In the function definition, the formal parameters must be an array type and the size of
second dim should be specified.
 The function prototype must show that the argument is an array.

/*PASSING A WHOLE 2-D ARRAY TO A FUN*/

#include<stdio.h>
#include<conio.h>
void fun ( int [ ] [ ] , int, int ) ; // function declaration
void main ( )
{
int a [ ] [2] = { {1 , 2 } , { 3 , 4 } } ;
clrscr ( ) ;
fun ( a , 2 , 2 ) ; // function call
getch ( ) ;
}
void fun(int x[ ] [ 2 ] , int m , int n)
{
int i , j ;
for ( i = 0 ; i < m ; i ++)
{
for ( j = 0 ; j < n ; j ++)
{
printf ( " \n a [ %d ] [ %d] = %d " , i , j , x [ i ] [ j ] ) ;
}
}
}

OUTPUT:

a [0] [0] = 1
a [0] [1] = 2
a [1] [0] = 3
a [1] [1] = 4
RECURSION:

Recursion is the process in which a function calls itself and the corresponding function is
called as recursive function.

 Using recursion we can avoid loops.


 Recursion always consists of two main parts. A terminating case or base case that
indicates when the recursion function will finish and a call to itself that must make
progress towards the terminating case.
 Whenever recursion is used we have to write if condition to terminate recursive function
calls, otherwise it will go into an infinite loop.

For Example, recursion may be applied to sorting, searching, and traversal


problems, Tower of Hanoi, Fibonacci series, factorial finding, etc.
/*PROGRAM TO FIND THE FACTORIAL OF A NUMBER USING RECURSION*/
# include < stdio . h >
# include < conio . h >
int fact ( int ) ; // function declaration
void main ( )
{
int n , f ;
clrscr ( ) ;
printf ( " \n Enter Number : " ) ;
scanf ( " %d " , &n ) ;
f = fact ( n ) ; // function call
printf ( " \n %d ! = %d " , n , f ) ;
getch ( ) ;
}
int fact ( int m ) // function definition
{
if ( m = = 1 ) // base case
return 1 ;
else
return m * fact ( m - 1 ) ; // recursive function call
}

OUTPUT:

Enter Number: 5
5 ! = 120

Explanation of factorial recursion


/*PROGRAM TO PRINT THE FIBONACCI SERIES USING RECURSION*/

# include < stdio . h >


# include < conio . h >
fibo ( int ) ; // function declaration
void main ( )
{
int i , n ;
clrscr ( ) ;
printf ( " \n How many Fibonacci Numbers you need: " ) ;
scanf ( " %d " , &n ) ;
printf ( " \n The Fibonacci Series of %d Terms is: \n " , n ) ;
for ( i = 1 ; i < = n ; i + + )
{
printf ( " %d " , fibo ( i ) ) ; //function call
}
getch ( ) ;

fibo ( int n ) // function definition


{
if ( n = = 1 ) // base case
return 0 ;
if ( n = = 2 ) // base case
return 1 ;
else
return (fibo ( n - 1 ) + fibo ( n - 2 ) ) ; // recursive function call
}

OUTPUT:
How many Fibonacci Numbers you need: 5
The Fibonacci Series of 5 Terms is:
0 1 1 2 3
/*PROGRAM TO PRINT THE GCD & LCM OF 2 NUMBERS USING RECURSION*/

# include < stdio . h >


# include < conio . h >
int gcd ( int , int ) ; // function declaration
void main ( )
{
int x , y , z , lcm ;
clrscr ( ) ;
printf ( " \n Enter Two Numbers: " ) ;
scanf ( " %d %d " , &x , &y ) ;
z = gcd ( x , y ) ; // function call
printf ( " \n GCD ( %d , %d ) = %d " , x , y , z ) ;
lcm = ( x * y ) / z ;
printf ( " \n LCM ( %d , %d ) = %d " , x , y , lcm ) ;
getch ( ) ;
}
int gcd ( int a , int b ) // function definition
{
if ( a = =0 || b = = 1 || a = = b ) // base case
return b ;
if ( a = = 1 || b = = 0 )
return a ;
if ( a > b )
return gcd ( b , a % b ) ; // recursive function call
else
return gcd ( a , b % a ) ; // recursive function call
}

OUTPUT:
Enter Two Numbers: 36 84
GCD ( 36 , 84 ) = 12
LCM ( 36 , 84 ) = 252
Limitations of Recursion:

 Recursion function makes program clearer and simpler.


 Recursion achieves repetition by calling the same function repeatedly.
 Recursion uses more processor time and memory usage.
 If the speed of the program is critical then, you should avoid using recursion.
 Recursion is terminated when base case ( if statement ) is satisfied. Means there should
be at least one base case must be a condition to stop recursion.
 Recursion is infinite if there is no base case ( if statement ) or if base case never reaches.
 If base case is not reached or not defined, then stack overflow problem may arise.

int fact ( int n )


{
// wrong base case (it may cause stack overflow).
if (n = = 100)
return 1 ;
else
return n * fact ( n - 1 ) ;
}

If fact (10) is called, it will call fact (9), fact (8), and fact (7) and so on but
number will never reach 100. So, the base case is not reached. If the memory is exhausted
by these functions on stack, it will cause stack overflow error.
DYNAMIC MEMORY ALLOCATION:

Memory can be reserved for the variables either during compilation or during execution
time (Run time). Memory can be allocated for variables using two different techniques,

1. Static memory allocation


2. Dynamic memory allocation

Static memory Allocation:

The process of allocating memory at compile time is called “ static memory allocation ”.
In this technique, once the size of the memory allocated is fixed, it cannot be
altered even during execution time.
Disadvantage: If the memory is allocated for various during compilation time , the
allocated memory space cannot be expanded to accommodate more data or cannot be
reduced to accommodate less data.

Ex: int a [ 10 ] ;

From above example, during compilation, the compiler will allocate 10 memory
locations for the variable a. in the worst case, 10 elements can be inserted or less than 10
elements lead to under utilization of allocated space and more than 10 elements cannot be
inserted.

Dynamic memory allocation:

The process of allocating memory during execution time (Run time) is called Dynamic
memory allocation
 We change the memory allocations for each execution of a program.
 This allocation technique uses predefined functions to allocate and release
memory for data during execution time.
 This allocation avoids the wastage of memory space (which is done in arrays).
 Dynamic allocation will be used commonly in the following data structures,
1. Dynamic arrays
2. Linked lists, Trees..etc
Memory allocation process

 The program instructions and global variables are stored in an area in memory called
"Permanent Storage Area".
 The local variables stored in memory are called "Stack".
 The area between stack and permanent storage is called "Heap" which is used for
dynamic memory allocation.

Memory management functions:

The various predefined memory management functions that are used to allocate or
deallocate memory dynamically.

Dynamic memory allocations can be done using fallowing functions


1. malloc 2. calloc 3. realloc 4. free

1. malloc

The malloc ( ) function is used to allocate a single block of memory of the


specified size. As the memory allocated in heap we can access the data through pointers.

Syntax: ptr = ( data type * ) malloc ( byte size ) ;

Where,
ptr is a pointer variable of data type
data type can be any of the basic data type
byte size is the total no of bytes required.

Ex: int * a ;
a = ( int * ) malloc ( 20 ) ;
This function returns the following values,

 On successful allocation, the function returns the address of first byte of allocated
memory.
 On unsuccessful allocation (if specified size of memory is not available), the function
returns NULL.

/* program to demonstrate malloc ( ) */


#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
void main ( )
{
int n , *a , i ;
clrscr ( ) ;
printf ( " \n Enter the size of an array: " ) ;
scanf ( " %d " , &n ) ;
a = ( int * ) malloc ( n * sizeof ( int ) ) ;
if ( a = = NULL )
{
printf (" \n insufficient memory " ) ;
return ;
}
printf ( " \n Enter %d elements : \n" ) ;
for ( i = 0 ; i < n ; i + + )
scanf ( " %d " , a + i ) ;
printf ( " \n Elements are : \n" ) ;
for ( i = 0 ; i < n ; i + + )
printf ( " \t %d " , * ( a + i ) ) ;
free ( a ) ;
getch ( ) ;
}
OUTPUT:
Enter the size of an array: 5
Enter 5 elements :
10 20 30 40 50
Elements are :
10 20 30 40 50
2. calloc :

 This function is used to allocate multiple blocks of memory/storage.


 By default all the locations will be initialized to zero.
 It is specifically used to store structures.

syntax: ptr = ( data type * ) calloc ( n , size ) ;

Where,
ptr, is a pointer variable of data type
data type, can be any of the basic data type
n, is the number of blocks to be allocated.
Size, no. of bytes in each block.

Thus, total number of bytes allocated is n*size.

Ex: int * a ;
a = ( int * ) calloc ( 5, sizeof ( int ) ) ;

Here, calloc ( ) function allocates 5 blocks of memory with 2 bytes each,


initializes each byte to 0 and returns the address of the first byte. Thus returned
address is stored in pointer variable a .

This function returns the following values,

 On successful allocation, the function returns the address of first byte of allocated
memory.
 On unsuccessful allocation (if specified size of memory is not available), the function
returns NULL.
/* program to find maximum of n numbers using dynamic arrays */
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
void main ( )
{
int n , *a , i , j ;
clrscr ( ) ;
printf ( " \n Enter the size of an array: " ) ;
scanf ( " %d " , &n ) ;
a = ( int * ) calloc ( n , sizeof ( int ) ) ;
if ( a = = NULL )
{
printf (" \n insufficient memory " ) ;
return ;
}
printf ( " \n Enter %d elements : \n " , n ) ;
for ( i = 0 ; i < n ; i + + )
scanf ( " %d " , &a[ i ] ) ;
j=0;
for ( i = 1 ; i < n ; i + + )
{
if (a [ i ] > a [ j ] )
{
j=i;
}
}
printf ( " \n The biggest = %d is found at %d location " , a [ j ] , j + 1 ) ;
free ( a ) ;
getch ( ) ;
}
OUTPUT:
Enter the size of an array: 5
Enter 5 elements :
8 10 15 4 5
The biggest = 15 is found at 3 location
3. realloc

This function is used increase/decrease the size of already allocated memory.

 Before using this function, the memory should have been allocated using malloc ( ) or
calloc ( ).
 realloc ( ) changes the size of the block by extending or deleting the memory at the
end of the block.

syntax: ptr = ( data type * ) realloc ( ptr , new size ) ;

Where,
ptr, is a pointer variable to a block of previously allocated memory.
data type, can be any of the basic data type
Size, is new size of the block.

Ex: int * a ;
a = ( int * ) realloc ( a, sizeof ( int ) ) ;

This function returns the following values,

 On successful allocation, the function returns the address of first byte of allocated
memory.
 On unsuccessful allocation (if specified size of memory is not available), the function
returns NULL.

/*PROGRAM TO demonstrate realloc()*/

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
void main ( )
{
char *str ;
clrscr ( ) ;
str = ( char * ) malloc ( 10 ) ;
strcpy ( str , " PROGRAMMING " ;
printf ( " \n %s " , str ) ;
str = ( char * ) realloc ( str , 20 ) ;
strcpy ( str , " PROGRAMMING FOR PROBLEM SOLVING " );
printf ( " \n %s " , str ) ;
free ( str ) ;
getch ( ) ;
}

OUTPUT:

PROGRAMMING
PROGRAMMING FOR PROBLEM SOLVING

4. free ( )

This function is used to de-allocate the allocated block of memory which is


allocated by using malloc ( ) , calloc ( ) , realloc ( ).
This is used to release the memory at runtime whenever it is not required by the
program and initialize ptr to NULL.

syntax: free ( ptr ) ;

Ex: int * a ;
free ( a ) ;

You might also like