Unit IV - Functions
Unit IV - 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".
"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.
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 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:
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.
Syntax:
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:
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:
We can write more than one return statement using if-else statement.
This statement will return the control back to the calling function.
Examples:
#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:
#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
#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:
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:
OUTPUT:
Enter 2 integers: 10 20
Sum = 30
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.
#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
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
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:-
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.
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:
Now, let see the difference between actual parameters and formal parameters:
There are 2 ways in which we can pass arguments or parameters to a function, they are
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.
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.
#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
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
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
OUTPUT:
1 2 3 4 5
OUTPUT:
OUTPUT:
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.
#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.
OUTPUT:
Enter Number: 5
5 ! = 120
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*/
OUTPUT:
Enter Two Numbers: 36 84
GCD ( 36 , 84 ) = 12
LCM ( 36 , 84 ) = 252
Limitations of Recursion:
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,
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.
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.
The various predefined memory management functions that are used to allocate or
deallocate memory dynamically.
1. malloc
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.
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.
Ex: int * a ;
a = ( int * ) calloc ( 5, sizeof ( int ) ) ;
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
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.
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 ) ) ;
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.
#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 ( )
Ex: int * a ;
free ( a ) ;