UNIT-IV FUNCTIONS AND 9
POINTER
Functions:- Need for functions, Elements of User-defined Functions, Definition of Functions, Return Values
and their Types, Function Calls, Function Declaration, Category of Functions, No Arguments and no Return
Values, Arguments but no Return values, Arguments with Return Values, No Arguments but Returns a
Value, Passing Arrays to Functions, Recursion, The Scope, Visibility and Lifetime of variables.
Pointers:- Introduction, Declaring Pointer Variables, Initialization of Pointer variables, accessing a Variable
through its Pointer, Pointer Expressions, Pointer Increments and Scale Factor. Example Problems
Introduction to functions
A function is a subprogram of one or more statements that performs a specific task when called.
Functions are created when the same process or an algorithm to be repeated several times in
various places in the program.
Function has a self-contained block of code,that executes certain task. A function has a name, a
list of arguments which it takes when called, and the block of code it executes when called.
Need for functions
A function is a block of code which only runs when it is called. You can pass data, known as parameters,
into a function. Functions are used to perform certain actions, and they are important for reusing code:
Define the code once, and use it many times.
Advantages of Functions:
1. Code reusability
2. Better readability
3. Reduction in code redundancy
4. Easy to debug & test.
Classification of functions:
• Based on who develops the function
• Based on the number of arguments a function accepts
Based on who develops the function
There are two types.
1. Library functions
2. User-defined functions
1. Library functions [Built-in functions]
Library functions are predefined functions. These functions are already developed by someone
and are available to the user for use. Ex. printf( ), scanf( ).
2. User-defined functions
User-defined functions are defined by the user at the time of writing a program. Ex. sum( ),
square( )
Using Functions
A function can be compared to a black box that takes in inputs, processes it, and then outputs the
result.
Terminologies using functions are:
▪ A function f that uses another function g is known as the calling function, and g is known
as the called function.
▪ The inputs that a function takes are known as arguments.
▪ When a called function returns some result back to the calling function, it is said to return
that result.
▪ The calling function may or may not pass parameters to the called function. If the called
function accepts arguments, the calling function will pass parameters, else not.
▪ Function declaration is a declaration statement that identifies a function’s name, a list of
arguments that it accepts, and the type of data it returns.
▪
Function definition consists of a function header that identifies the function, followed by
the body of the function containing the executable code for that function.
Function definition
When a function is defined, space is allocated for that function in the memory. A function
definition comprises of two parts:
▪ Function header
▪ Function body
The syntax of a function definition can be given as:
return_data_type function_name(data_type variable1, data_type variable2,..) {
.............
Statements
.............
Return (variable);
}
While return_data_type function_name(data_type variable1, data_type variable2,...) is
known as the function header, the rest of the portion comprising of program statements within
the curly brackets { } is the function body which contains the code to perform the specific task.
Note that the function header is same as the function declaration. The only difference
between the two is that a function header is not followed by a semi-colon.
Function Prototype
Before using a function, the compiler must know the number of parameters and the type
of parameters that the function expects to receive and the data type of
value that it will return to the calling program. Placing the function declaration
statement prior to its use enables the compiler to make a check on the arguments
used while calling that function.
Syntax:
return_data_type function_name(data_type variable1, data_type variable2,..);
Here, function_name is a valid name for the function. Naming a function follows the
same rules that are followed while naming variables. A function should have a meaningful name
that must specify the task that the function will perform.
return_data_type specifies the data type of the value that will be returned to the calling
function as a result of the processing performed by the called function.
(data_type variable1, data_type variable2, ...) is a list of variables of specified data
types.
These variables are passed from the calling function to the called function. They are also
known as arguments or parameters that the called function accepts to perform its task.
Function Call
The function call statement invokes the function. When a function is invoked, the compiler
jumps to the called function to execute the statements that are a part of that function. Once the
called function is executed, the program control passes back to the calling function.
Syntax:
function_name(variable1, variable2, ...);
The following points are to be noted while calling a function:
▪ Function name and the number and the type of arguments in the function call must be
same as that given in the function declaration and the function header of the function
definition.
▪ Names (and not the types) of variables in function declaration, function call, and header
of function definition may vary.
▪ Arguments may be passed in the form of expressions to the called function. In such a
case, arguments are first evaluated and converted to the type of formal parameter and
then the body of the function gets executed.
If the return type of the function is not void, then the value returned by the called function
may be assigned to some variable as given below.
variable_name function_name(variable1, variable2, ...);
Working of a function
void main()
{
int x,y,z;
int abc(int, int, int) // Function declaration …..
…..
abc(x,y,z) // Function Call
… Actual arguments
…
}
int abc(int i, int j, int k) // Function definition
{ Formal arguments
…….
….
return (value);
}
Calling function – The function that calls a function is known as a calling function.
Called function – The function that has been called is known as a called function
FUNCTION ASPECTS: SYNTAX
1 function definition
Return type function name (arguments list)
{Body of function ;}
2 function call
function_name ( arguments list );
3 function declaration
return_type function_name (argument list);
Function Parameters:
Parameters provide the data communication between calling function and called function.
Two types:
Actual parameters:
These are the parameters transferred from the calling function [main function] to the called
function [user defined function].
Formal parameters:
Passing the parameters from the called functions [user defined function] to the calling functions
[main function].
Categories of User defined function/Function Prototypes:
A function prototype declaration consists of the function‟s return type, name and arguments
list.
Always terminated with semicolon. The following are the function prototypes:
1. Function without return value and without argument.
2. Function without return value and with argument.
3. Function with return value and with argument.
4. Function with return value and without argument.
Note: Function with more than one return value will not have return type and return statement
in the function definition.
Consider the following example to multiply two numbers:
void main( )
{
int x,y,z;
scanf(“%d%d”, &x,&y);
z=x* y;
printf(“The result is %d”, z);
1. Function without return value and without argument
In this prototype, no data transfers takes place between the calling function and the called
function. They read data values and print result in the same block.
Syntax:
void f_name(); //function declaration
void f_name (void) //function definition
local variables; statements;
}
void main()
f_name(); //function call
The above example can be rewritten by creating function:
void f_mult(); //function definition void f_mult(void )
int x,y,z; scanf(“%d%d”, &x,&y); z=x* y;
printf(“The result is %d”, z);
void main()
f_mult();
2. Function without return value and with argument
In this prototype, data is transferred from the calling function to called function. The called
function receives some data from the calling function and does not send back any values to the
calling functions.
Syntax:
void f_name(int x, int y ); //Function declaration
void f_name (int x, int y) //Function Definition //Formal Parameters
local variables;
statements;
void main()
//variable declaration //input statement
f_name(c, d); //Function call //Actual Parameters
The above example can be rewritten by creating function void f_mult(int x, int y);
void f_mult(int x, int y )
{
int z; z=x* y;
printf(“The result is %d”, z);
void main()
int c, d;
printf(“Enter any two number”); scanf(“%d%d”, &c, &d); f_mult(c, d); //Function call
3. Function with return value and without argument
The calling function cannot pass any arguments to the called function but the called
function may send some return value to the calling function.
Syntax:
int f_name(); //Function declaration
int f_name (void) //Function Definition
{
local variables;
statements;
return int;
}
void main()
{
//variable declaration
ret_var=f_name(); //Function call
The above example can be rewritten by creating function int f_mult();
int f_mult(void )
int x,y,z; scanf(“%d%d”, &x,&y); z=x* y;
printf(“The result is %d”, z); return(z); }
void main()
int c; c=f_mult(); getch();
}
4. Function with return value and with argument
In this prototype, the data is transferred between the calling function and called function.
The called function receives some data from the calling function and send back a value return to
the calling function.
Syntax:
int f_name (int x, int y); //Function declaration
int f_name (int x, int y) //Function definition //Formal Parameters
local variables;
statements;
return int;
void main()
//variable declaration //Input Statement
ret_value=f_mult(a, b); //Function Call //Actual Parameters
The above example can be rewritten by creating function: int f_mult(int x, int y);
int f_mult(int x, int y)
int z; z=x* y;
printf(“The result is %d”, z); return(z);
}
void main()
int a,b,c;
printf(“Enter any two value:”); scanf(“%d%d”, &a, &b); c=f_mult(a, b);
Note:
If the return data type of a function is “void”, then, it can‟t return any values to the calling
function.
If the return data type of the function is other than void such as “int, float, double etc”, then,
it can return values to the calling function.
return statement:
It is used to return the information from the function to the calling portion of the program.
Syntax:
return;
return();
return(constant);
return(variable);
return(exp); return(condn_exp);
By default, all the functions return int data type.
Do you know how many values can be return from C functions?
Always,only one value can be returned from a function.
If you try to return more than one values from a function, only one value will be returned
that appears at the right most place of the return statement.
For example, if you use “return a,b,c” in your function, value for c only will be returned and
values a, b won‟t be returned to the program.
In case, if you want to return more than one values, pointers can be used to directly change
the values in address instead of returning those values to the function.
Passing Arrays to Functions
Parameter Passing Methods/Argument Passing Methods
Call by Value/Pass by Value:
When the value is passed directly to the function it is called call by value. In call by value only a
copy of the variable is only passed so any changes made to the variable does not reflects in the
calling function.
Example:
#include<stdio.h>
#include<conio.h>
swap(int,int); void main()
{
int x,y;
printf("Enter two nos"); scanf("%d %d",&x,&y);
printf("\nBefore swapping : x=%d y=%d",x,y); swap(x,y);
getch();
swap(int a,int b)
int t; t=a; a=b; b=t;
printf("\nAfter swapping :x=%d y=%d",a,b);
System Output:
Enter two nos 12 34
Before swapping :12 34
After swapping : 34 12
Call by Reference/Pass by Reference:
When the address of the value is passed to the function it is called call by reference. In call
by reference since the address of the value is passed any changes made to the value reflects in the
calling function.
Example:
#include<stdio.h>
#include<conio.h> swap(int *, int *); void main()
{
int x,y;
printf("Enter two nos"); scanf("%d %d",&x,&y);
printf("\nBefore swapping:x=%d y=%d",x,y); swap(&x,&y);
printf("\nAfter swapping :x=%d y=%d",x,y); getch();
swap(int *a,int *b)
int t; t=*a; *a=*b; *b=t;
}
System Output:
Enter two nos 12 34
Before swapping :12 34
After swapping : 34 12
Call by Value
This is the usual method to call a function in which only the value of the variable is passed as an
argument
Any alternation in the value of the argument passed does not affect the function.
Memory location occupied by formal and actual arguments is different
Since a new location is created, this method is slow
There is no possibility of wrong data manipulation since the arguments are directly used in an
application
Call by Reference
In this method, the address of the variable is passed as an argument
Any alternation in the value of the argument passed affect the function.
Memory location occupied by formal and actual arguments is same and there is a saving of
memory location
Since the existing memory location is used through its address, this method is fast
There is a possibility of wrong data manipulation since the addresses are used in an expression. A
good skill of programming is required here
Library Functions:
C language provides built-in-functions called library function compiler itself evaluates
these functions.
List of Functions
Sqrt(x) -- > (x)0.5
Log(x)
Exp(x)
Pow(x,y)
Sin(x)
Cos(x)
Rand(x)-> generating a positive random integer.
Recursion in C:
Recursion is calling function by itself again and again until some specified condition has
been satisfied.
Syntax:
int f_name (int x)
local variables;
f_name(y); // this is recursion statements;
}
Recursion
A function that calls itself is known as a recursive function.
Direct & Indirect Recursion:
Direct Recursion:
A function is directly recursive if it calls itself.
A( )
{
….
….
A( );// call to itself
….
}
Indirect Recursion:
Function calls another function, which in turn calls the original function.
A( )
{
…
…
B( );
…
}
B( )
{
…
…
A( );// function B calls A
…
}
Consider the calculation of 6! ( 6 factorial )
ie 6! = 6 * 5 * 4 * 3 * 2 * 1
6! = 6 * 5!
6! = 6 * ( 6 - 1 )!
n! = n * ( n - 1 )!
Types of Recursion
Direct Recursion
A function is said to be directly recursive if it explicitly calls itself. Here, the function Func()
calls itself for all positive values of n, so it is said to be a directly recursive function.
int Func (int n)
{
if (n == 0)
return n;
else
return (Func (n–1));
}
Indirect Recursion
A function is said to be indirectly recursive if it contains a call to another function which
ultimately calls it. These two functions are indirectly recursive as they both call each other.
int Funcl (int n)
{
if (n == 0)
return n;
else
return Func2(n);
}
int Func2(int x)
{
return Func1(x–1);
}
Tail Recursion
A recursive function is said to be tail recursive if no operations are pending to be performed
when the recursive function returns to its caller. When the called function returns, the returned
value is immediately returned from the calling function.
int Fact(int n)
{
if (n == 1)
return 1;
else
return (n * Fact(n–1));
}
The above function is a nontail-recursive function, because there is a pending operation of
multiplication to be performed on return from each recursive call. Whenever there is a pending
operation to be performed, the function becomes non-tail recursive. In such a non-tail recursive
function, information about each pending operation must be stored, so the amount of information
directly depends on the number of calls.
int Fact(n)
{
return Fact1(n, 1);
}
int Fact1(int n, int res)
{
if (n == 1)
return res;
else
return Fact1(n–1, n*res);
}
The same factorial function can be written in a tail recursive manner. In the code, Fact1 function
preserves the syntax of Fact(n). Here the recursion occurs in the Fact1 function and not in Fact
function. Fact1 has no pending operation to be
performed on return from recursive calls. The value computed by the recursive call is simply
returned without any modification. So in this case, the amount of information to be stored on the
system stack is constant (only the values of n and res need to be stored) and is independent of the
number of recursive calls.
E.g. Program:
#include<stdio.h>
#include<conio.h>
void main()
{
int fact(int);
int n,f;
printf(“Enter the number \n”);
scanf(“%d”,&n);
f=fact(n);
printf(“The factorial of a number =%d”,f);
getch();
}
int fact(int n)
{
if(n==1)
return(1);
else
return n*fact(n-1);
}
OUTPUT
Enter the number to find the factorial
5
The factorial of a number=120
Pattern of Recursive Calls:
Based on the number of recursive calls, the recursion is classified in to 3 types. They
are,
1. Linear Recursion - Makes only one recursive call.
2. Binary Recursion - Calls itself twice.
3. N-ary recursion - Calls itself n times.
Converting Recursive Functions to Tail Recursive
A non-tail recursive function can be converted into a tail-recursive function by using an
auxiliary parameter as we did in case of the Factorial function. The auxiliary parameter is used to
form the result. When we use such a parameter, the pending operation is incorporated into the
auxiliary parameter so that the recursive call no longer has a pending operation.
Recursive functions can also be characterized depending on the way in which the recursion
grows in a linear fashion or forming a tree structure as shown below:
int Fibonacci(int num)
{
if(num == )
return ;
else
return (Fibonacci(num - 1) + Fibonacci(num – 2));
}
else if (num == 1)
return 1;
Observe the series of function calls. When the function pending operations in turn calls the
function
Fibonacci(7) = Fibonacci(6) + Fibonacci(5)
Fibonacci(6) = Fibonacci(5) + Fibonacci(4)
Fibonacci(5) = Fibonacci(4) + Fibonacci(3)
Fibonacci(4) = Fibonacci(3) + Fibonacci(2)
Fibonacci(3) = Fibonacci(2) + Fibonacci(1)
Fibonacci(2) = Fibonacci(1) + Fibonacci(0) Now
we have, Fibonacci(2) = 1 + 0 = 1 Fibonacci(4) =
2 + 1 = 3 Fibonacci(5) = 3 + 2 = 5
Fibonacci(6) = 3 + 5 = 8
Fibonacci(7) = 5 + 8 = 13
On the contrary, a recursive function is said to be tree recursive (or non-linearly
recursive) if the pending operation makes another recursive call to the function. For example, the
Fibonacci function in which the pending operations recursively call the Fibonacci function.
3.7 Example Program
Program for Computation of Sine series
#include<stdio.h>
#include<conio.h>
#include<math.h>
void main()
{
int i, n ;
float x, val, sum, t ;
clrscr() ;
printf("Enter the value for x : ") ;
scanf("%f", &x) ;
printf("\nEnter the value for n : ") ;
scanf("%d", &n) ;
val = x ;
x = x * 3.14159 / 180 ;
t=x;
sum = x ;
for(i = 1 ; i < n + 1 ; i++)
{
t = (t * pow((double) (-1), (double) (2 * i - 1)) * x * x) / (2 * i * (2 * i + 1)) ; sum = sum
+t;
}
printf("\nSine value of %f is : %8.4f", val, sum) ; getch()
;
}
Output:
Enter the value for x : 30
Enter the value for n : 20
Sine value of 30.000000 is : 0.5000
Scientific calculator using built-in functions Program for binary search using recursive
function
#include<stdio.h>
int main()
{
int a[10],i,n,m,c,l,u;
printf("Enter the size of an array: ");
scanf("%d",&n);
printf("Enter the elements of the array: " );
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
printf("Enter the number to be search: ");
scanf("%d",&m);
l=0,u=n-1;
c=binary(a,n,m,l,u);
if(c==0)
printf("Number is not found.");
else
printf("Number is found.");
return 0;
}
int binary(int a[],int n,int m,int l,int u)
{
int mid,c=0;
if(l<=u)
{
mid=(l+u)/2;
if(m==a[mid])
{
c=1;
}
else if(m<a[mid])
{
return binary(a,n,m,l,mid-1);
}
else
return binary(a,n,m,mid+1,u);
}
else
return c;
}
Output:
Enter the size of an array: 5
Enter the elements of the array: 8 9 10 11 12
Enter the number to be search: 8
Number is found.
Example_1: Factorial using Recursion
#include<stdio.h>
#include<conio.h> int factorial(int n); void main()
{
int res,x;
printf(“\n Enter the value:”); scanf(“%d”, &x); res=factorial(x);
printf(“The factorial of %d is ..%d”, res);
int factorial(int n)
int fact; if (n==1) return(1); else
fact = n*factorial(n-1); return(fact); }
Example_2: Fibonacci using Recursion
#include<stdio.h>
#include<conio.h> int Fibonacci(int); int main()
{
int n, i = 0, c; scanf("%d",&n); printf("Fibonacci series\n"); for ( c = 1 ; c <= n ; c++ )
printf("%d\n", Fibonacci(i)); i++;
return 0;
int Fibonacci(int n)
if ( n == 0 ) return 0;
else if ( n == 1 ) return 1;
else
return ( Fibonacci(n-1) + Fibonacci(n-2) );
}
Example_3: Sum of n Natural Numbers
#include<stdio.h>
#include<conio.h> int add(int n); void main()
{
int m, x;
printf("Enter an positive integer: "); scanf("%d",&m);
x=add(m); printf("Sum = %d", x); getch();
int add(int n)
if(n!=0)
return n+add(n-1); /* recursive call */
}
Pointers
Definition:
A pointer is a variable that stores the address of a variable or a function Advantages
1. Pointers save memory space
2. Faster execution
3. Memory is accessed efficiently.
Declaration
datatype *pointername;
E.g ) int *p //p is an pointer to an int
float *fp //fp is a pointer to a float
int a=10; p a
int *p=&a;
2000 10
4000 2000
p is an integer pointer & holds the address of an int variable a.
Pointer to pointer
A pointer that holds the address of another pointer variable is known as a pointer to pointer.
E.g.
int **p;
p is a pointer to a pointer to an integer.
int a=12;
int *p=&a; a
int **pptr=&p;
12
p 4000 4000
6000
6000
pptr
8000
So **pptr=12
3.9 Operations on pointers
1. Referencing operation: A pointer variable is made to refer to an object. Reference
operator(&) is used for this. Reference operator is also known as address of (&)
operator.
Eg) float a=12.5;
float *p;
p=&a;
a 12.5
1000
1000
P
2000
2. Dereferencing a pointer
The object referenced by a pointer can be indirectly accessed by dereferencing the
pointer. Dereferencing operator (*) is used for this .This operator is also known as
indirection operator or value- at-operator
Eg) int b;
int a=12;
12
a int *p;
1000
1000 p=&a;
b=*p; \\value pointed by p(or)value
at 1000=12,
p so b=12
2000
Example program
#include<stdio.h>
Note
void main()
{
int a=12; %p is used for addresses; %u
int *p; can also be used.
int **pptr;
*p=value at p
p=&a;
=value at (1000)=12
pptr=&p;
printf(“a value=%d”,a);
*pptr=value at(pptr)
printf(“value by dereferencing p is %d \n”,*p);
=value at(value at (2000))
printf(“value by dereferencing pptr is %d \n”,**pptr);
=value at (1000)=12
printf(“value of p is %u \n”,p);
printf(“value of pptr is %u\n”,pptr);
}
Output:
a value=12
value by dereferencing p is 12
value by dereferencing pptr is 12
value of p is 1000
value of pptr is 2000
a 12
1000 p 1000
2000
2000 pptr
3000
3.10 Pointer arithmetic
Arithmetic operations on pointer variables are also possible.
E.g.) Addition, Increment, Subtraction, Decrement.
1. Addition
(i) An addition of int type can be added to an expression of pointer type. The result is pointer
type.(or)A pointer and an int can be added.
Eg) if p is a pointer to an object then p+1 =>points to
next object p+i=>point s to ith object
after p
(ii)Addition of 2 pointers is not allowed.
2. Increment
Increment operator can be applied to an operand of pointer type.
3. Decrement
Decrement operator can be applied to an operand of pointer type.
4. Subtraction
i) A pointer and an int can be subtracted.
ii) 2 pointers can also be subtracted.
3.11. Pointers and Arrays
In C language, pointers and arrays are so closely related.
i) An array name itself is an address or pointer. It points to the address of first
element (0th element) of an array.
Example
#include<stdio.h
> void main()
{
int a[3]={10,15,20};
printf(“First element of array is at %u\n”, a);
10 15 20
nd
printf(“2 element of array is at %u\n”, a+1);
printf(“3nd element of array is at %u\n”, a+2);
1000 1002 1004
}
Output
First element of array is at 1000
2nd element of array is at 1002
3nd element of array is at 1004
ii ) Any operation that involves array subscripting is done by using pointers in c language.
E.g.) E1[E2]=>*(E1+E2)
Example
#include<stdio.h>
void main()
{
int a[3]={10,15,20};
printf(“Elements are %d %d %d\n”, a[0],a[1],a[2]);
printf(“Elements are %d %d %d\n”, *(a+0),*(a+1),*(a+2);
}
Output:
Elements are 10 15 20
Elements are 10 15 20
Array of pointers
An array of pointers is a collection of addresses. Pointers in an array must be the same
type.
int a=10,b=20,c=30;
int *b[3]={&a,&b,&c};
a b c
10 20 30
4000 4100 4400
4000 4100 4400
Now look at another code in which we store the address of three individual arrays
in the array of pointers:
int main()
{
int arr1[]={1,2,3,4,5};
int arr2[]={0,2,4,6,8};
int arr3[]={1,3,5,7,9};
int *parr[3] = {arr1, arr2, arr3};
int i;
for(i = 0;i<3;i++)
printf(«%d», *parr[i]);
return 0;
Exampl }
e:
Output
101