User Defined Functions
User Defined Functions
Introduction:
As programs grow large in size and complexity, it becomes very difficult to keep track of the logic.
Therefore at this stage the program are divided into smaller modules called functions where each
module can be coded separately and tested. Later these modules are combined into a single program.
Library functions: they are built-in functions and ready to use. The user need not write these
functions.
User-defined functions: The user must develop these functions.
1. Whenever the same set of statements are to be repeated many times in various parts of the
program, these statements can be placed in a function and invoked wherever required.
2. When User-Defined Functions are used in a program, it reduces the number of lines of code.
3. Debugging becomes easier as the program is divided into number of functions.
4. Usage of UDFs leads to modular and structured programming.
5. UDFs can be included in the C library allowing other users to utilize them.
1. Function Definition:
It’s also known as function implementation. It consists of the following elements:
---function type
---function name
---argument list
---local variables
---executable statements
---return statement
these elements forms the structure of a C function.
Structure of a C function:
data-type function-name (list of arguments/parameters) function header
{
local variable declaration;
executable statements; body/domain of the function
…………..
return statement;
}
Function header: It consists of 3 parts:
a) data – type
b) function – name
c) argument list.
a) data – type
i) Data-type denotes the data type of the result returned by the function.
ii) If the return type is omitted, it is assumed to be int.
iii) In general, it may be int, float, char, void (null) etc….
b) function name:
i) It is the name of the function which follows the rules of the identifier/variable name in C.
c) argument list:
i) It is the name of the function, which follows the rules of the identifier/variable name in C.
ii) It has the form: data-type function-name(type1 arg1, type2 arg2, ……, typen argn)
iii) The list of arguments/parameters should be separated with comma and to be enclosed within
parenthesis.
Note: no semicolon is placed at the end of function header.
Example:
int add(int a, int b)------- function header
{
……..
}
Local Variable declaration:
Here, we declare all the variable (local) whenever needed by that function.
These variables are local to the function in which they are declared.
Body of the function:
Contains the executable statements and declarations and local variables if any required to
perform the task and also a return statement the returns the value evaluated by the functions.
Return values and their types:
A function may return values or may not send back any values to the calling program.
It has two forms:
return;
return(expression);
The return statement is used to send back the values from the sub-program /
function to the main function.
A function can return one value or none for every function call.
General form:
return;
or
return(expression);
The 1st form of return statement is used when the function does not return any value to the
calling function.
In such a case, it is used to exit from a function.
Example: if(n<1)
return;
The second form of return statement returns the value of the expression. The expression within
parenthesis can be a numeric constant, variable/an expression.
Example:
int add(int a,int b)
{
int sum;
sum=a+b;
return(sum);
}
(Or)
add(int a,int b)
{
return(a+b);
}
A function must contain atleast one return statement. It can have more than one return
statement depending on the situation.
Example:
if(prime==1)
return(1);
else
return(0);
valid return statements are:
return; or return 0;
return 1; or return (1);
return(a+b); or return(sum);
Function name
Argument/parameter list
Terminating semicolon
/* function fun1() */
Fun1()
{
……..
}
/* function fun2() */
Fun2()
{
………
}
/* function fun3() */
Fun3()
{
,………
}
Fig: flow of control in a multi-function program
Nesting of functions:
Nesting of functions in a C program can be performed easily.
A function can call any other function.
A function can call itself.
A function can be called more than once.
main () can call function1() which calls function2() which in turn calls function3() etc…
Such type of function calls is referred to as a nest of functions. There is no limit to the nesting
levels.
int i,j,t;
for(i=0; i<=m-1; i++)
for(j=1; j<=m-1; j++)
if(x[ j-1] >= x[ j])
{
t = x[j-1];
x[j-1] = x[j];
x[j] = t;
}
}
Recursion is a process by which a function calls itself repeatedly until some specified condition is
satisfied.
This process is used for repeated calculations, where each action is in terms of a previous result.
Thus, recursive function is one, which uses itself in its own definition.
Eg: - function1(int y)
{
…
…
…
L=function1(y);
…
}
In order to use recursive functions, there are 2 conditions to be satisfied.
1. The program must be in recursive form.
2. It must include a terminating condition.
Recursive functions have a looping structure. Hence, it requires a terminating condition to exit
from the loop.
Eg: - consider the following example to calculate factorial of a positive integer: -
n! = n*(n-1)*(n-2)*…..*3*2*1
This can also be expressed as : n! = n*(n-1)!
This is a recursive statement in which the desired result is expressed in terms of a
previous result, which is assumed to be known.
Eg: - /* Program to calculate factorial of an integer using recursion */
#include<stdio.h>
#include<conio.h>
int fact(int);
void main()
{
int n;
clrscr();
printf("ENter the value of N: \n");
scanf("%d",&n);
printf("Factorial of %d is %d\n",n,fact(n));
getch();
}
int fact(int n)
{
if(n<2)
return n;
else
return (n*fact(n-1));
}
Explanation: -
When a recursive program is executed, the recursive function calls are not executed
immediately, but placed on a stack until the termination condition is encountered.
Next, the function calls are executed in reverse order and the result is returned to the calling
function.
Eg: - fact(4)
(4*fact(3))
(3*fact(2))
(2*fact(1))
Eg 2: - Fibonacci Series.
1, 1, 2, 3, 5, 8, 13……
The formula used is: fn = fn-1 + fn – 2
Given f0 = 0, fn = 1.
Thus summing the previous two terms of the series can generate every term.
i.e.., f0 = 0, when n = 0.
f1 = 1, when n =1
f2 = f1 + f0 = 1
f3 = f2 + f1 = 1 + 1 = 2 and so on.
Therefore, the recursive statement would be,
if (n==0)
return (0);
if (n==1)
return 1;
else
return ( fib(n-1) + fib(n-2));
In this method, the calling function sends copies of its data which are stored in temporary
storage locations. These values are used by the functions as local variables (formal Parameters).
Further, the results are processed, temporary variables are destroyed and result is returned to
the main program through return statement.
The formal parameters may change within the called function.
However, this does not affect the actual parameters, since only copies of data have been sent to
the called function.
Eg: -
#include<stdio.h>
swap(int,int); //Function Prototype
main()
{
int x = 10, y = 20;
printf(“Before calling swap: x = %d , y = %d”,x,y);
swap(x,y);
printf(“After calling swap : x = %d,y=%d”,x, y);
return;
}
swap(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
printf(“With swap function x = %d.y = %d”,x,y);
return;
}
10
X Y 20 X Y
Within Swap: -
Memory allocation for main program mem/ allocation for func/ swap.
10 20 20 10 10
X Y X Y Temp
After calling swap: -
Memory allocation for main program mem/ allocation for func/ swap.
10
X 20
Y X Y
The output of the above example shows that: X and Y are not altered in main () even though the
values are changed within the function swap.
The advantage is that: it allows only single valued argument to be used as actual argument and
protects the value of this variable from alteration within the function.
The disadvantage is that it does not allow information to be transferred back to the calling
program through arguments.
Thus, call by value is restricted to one way of transfer of information.
It allows transfer of zero or one value only through the return mechanism.
Call by reference: -
A function may be made to send back, as many values as required.
However, only one value may be sent through the return statement.
One way is to use global variables. Pointers provide another way.
We know that, the calling program variables remain unaffected in the call by value method.
However, when address of arguments are passed as actual parameters to the called function,
the function can change the contents stored at those addresses and these changes will be visible
in the calling function.
Therefore, a function with pointer variables as parameters can return several values to the
calling function.
It is important that the formal arguments of the called function receiving the addresses of the
actual arguments must be of pointer type.
The reason that scanf () uses pointers is to write new values into existing memory locations.
When pointers are used as arguments to a function, an asterisk(*) precede the formal pointer
arguments.
Function prototypes are also declared in the same manner.
Eg: -
/* swap two values using call by reference mechanism * /
#include<stdio.h>
swap(int * , int *)
main()
{
int x = 40, y = 20;
printf(“Before calling swap : x = %d, y =%d”, x , y);
swap(&x, &y);
printf(“After calling swap : x = %d, y = %d” , x , y);
return;
}
swap(int *x, int *y)
{
int temp;
temp = * x;
*x = *y;
*y = temp;
printf(“Within swap function : x= %d, y = %d”,x,y);
return;
}
Output: -
Before : x = 40 y = 20
Within : x = 20 y = 40 After : x = 20 y = 40
X Y
40 20
Within function swap: -
Memory allocation for main program change in the variable in memory of main prg.
X y p1 p2
After20
calling swap40: 20 40
Memory allocation for main program change in the variable in memory of main prg.
40 20 40 20
X y p1 p2
The address of x and y are passed on to the pointers p1 and p2 through the function call swap
(&x, &y).
Further, when the values of p1 and p2 are exchanged within the function the values of x and y
also get exchanged.
Comparison between call - by value and call - by reference
Call by Value
1. Calling function sends copies of data Call by reference
2. The formal parameters are ordinary variables. 1. Calling function sends addresses of data.
3. Results are sent to the calling function through 2. The formal parameters are pointer variables.
the return mechanism. Therefore, at most 3. Several results can be sent back to the calling
only one value can be sent back to the calling function.
function. 4. Direct changes are made to the actual
4. Actual parameters are unaffected by changes parameters.
made within the function.
Eg: /* program to show call by reference method can return several values */
#include<stdio.h>
main()
{
int x = 10, y = 5;
int sum , diff;
compute(x,y,&sum,&diff); //F. call
printf("sum of %d and %d = %d",x,y, sum);
printf("difference of %d and %d = %d",x,y,diff);
return;
}
compute(int a,int b, int *s,int *d)
{
*s = a+ b;
*d = a - b;
return;
}
Storage classes: -
The various information related to a datatype or a variable are: -
1. Name of variable.
2. Amount of space required to store that variable.
3. Address of the memory location where the variable is created.
There are 2 kinds of locations in a computer where the data in the variable are stored.
o Memory.
o CPU registers.
The storage class of the variable determines in which of the 2 locations, the value would be
stored.
A storage class is another modifier, which can be added to the variable declaration.
There are 4 storage classes in C: -
a) Automatic
b) Static
c) Register
d) External or extern
The syntax is: Storage-class datatype variable-name;
Storage classes and their meaning: -
1. Automatic variables: -
These are always created inside the body of the function.
They are created temporarily when the function is called and are destroyed automatically when
control is transferred back to the calling function.
Hence, they are referred to as automatic variables.
Since, they are created within the function; they are also known as local variables.
Any variable declared without a storage class becomes an automatic variable.
They are declared using the keyword auto.
Eg: - main()
{
auto int n;
…
…
}
The variables can be accessed directly inside any function by using the keyword extern.
They are accessed from the point of declaration to the end of program.
Extern declaration does not reserve storage space for variables. Therefore, variables cannot be
initialized in the declaration.
Arrays declared as extern should also include their size.
Eg: -
main()
{
int n,I;
-----
extern x;
extern float a[10];
sample();
-----
}
sample()
{
extern float a[10];
------
-------
}
One important feature of global variables is that if a function has local variables with the same
name as global variables, the local variables have precedence over the global.
C functions can be stored in separate files. If a variable is externally declared in file1 and needed
in the function of file2, the extern declaration can be used to make the variables accessible.
Static variables: -
The value of a static variable is retained until the end of the program.
A static variable can be declared using the keyword static as follows: -
o static int k;
o static float x;
A static variable will be initialized only once when declared inside a function. It is never
initialized again and again. When control is transferred back to the calling function, the static
variable is not destroyed but retains its value. Therefore, in repeated function calls it remembers
its previous value.
Static variables must be initialized only with constants.
Static variables are automatically initialized to zero.
Register Variables: -
Register variables are stored in the registers of the machine, instead of its memory locations.
Since a variable is stored in the registers it can be accessed faster than from memory.
Variables which are accessed frequently (like looping variables) are stored in the registers.
The variable declaration uses the keyword register as shown below: -
register int i;
Only few variables can be stored in registers.
If more number of variables are declared as register variables and if registers are not available to
store them, they will then be treated as automatic variables.
Comparison of global and local variables: -
Note: -When a local variable and global variable have the same name; the variable is treated as local
within the function. i.e.., local variable have higher precedence over global variables.
#include<stdio.h>
#include<conio.h>
fib(int);
void main()
{
int a1,a=0,b=1,c,n;
clrscr();
printf("Enter the value of N : ");
scanf("%d",&n);
printf("%4d%4d",a,b);
a1=fib(n);
printf("%4d",a1);
getch();
}
fib(int n)
{
if(n==0) return 0;
if(n==1) return 1;
else return(fib(n-1) + fib(n-2));
}