Pointers to functions
A pointer to a function points to the address of the executable code of
the function. You can use pointers to call functions and to pass
functions as arguments to other functions. You cannot perform
pointer arithmetic on pointers to functions.
Syntax of function pointer
1. return type (*ptr_name)(type1, type2…);
For example:
1. int (*ip) (int);
In the above declaration, *ip is a pointer that points to a function which returns
an int value and accepts an integer value as an argument.
1. float (*fp) (float);
In the above declaration, *fp is a pointer that points to a function that returns
a float value and accepts a float value as an argument.
We can observe that the declaration of a function is similar to the declaration
of a function pointer except that the pointer is preceded by a '*'. So, in the
above declaration, fp is declared as a function rather than a pointer.
Till now, we have learnt how to declare the function pointer. Our next step is to
assign the address of a function to the function pointer.
1. float (*fp) (int , int); // Declaration of a function pointer.
2. float func( int , int ); // Declaration of function.
3. fp = func; // Assigning address of func to the fp pointer.
In the above declaration, 'fp' pointer contains the address of
the 'func' function.
Calling a function through a function pointer
We already know how to call a function in the usual way. Now, we will see how to
call a function using a function pointer.
Suppose we declare a function as given below:
1. float func(int , int); // Declaration of a function.
Calling an above function using a usual way is given below:
1. result = func(a , b); // Calling a function using usual ways.
Calling a function using a function pointer is given below:
1. result = (*fp)( a , b); // Calling a function using function pointer.
Or
1. result = fp(a , b); // Calling a function using function pointer, and indirecti
on operator can be removed.
The effect of calling a function by its name or function pointer is the same. If we
are using the function pointer, we can omit the indirection operator as we did
in the second case. Still, we use the indirection operator as it makes it clear to
the user that we are using a function pointer.
1. #include <stdio.h>
2. int add(int,int);
3. int main()
4. {
5. int a,b;
6. int (*ip)(int,int);
7. int result;
8. printf("Enter the values of a and b : ");
9. scanf("%d %d",&a,&b);
10. ip=add;
11. result=(*ip)(a,b);
12. printf("Value after addition is : %d",result);
13. return 0;
14. }
15. int add(int a,int b)
16. {
17. int c=a+b;
18. return c;
19. }
Output
The type of a pointer to a function is based on both the return type
and parameter types of the function.
A declaration of a pointer to a function must have the pointer name in
parentheses. Function parameters have precedence over pointers in
declarations, so parentheses are required to alter the precedence and
declare a pointer to a function. Without them, the compiler interprets
the declaration as a function that returns a pointer to a specified
return type. For example:
int *f(int a); /* function f returning an int* */
int (*g)(int a); /* pointer g to a function returning an int */
In the first declaration, f is interpreted as a function that takes
an int as argument, and returns a pointer to an int. In the second
declaration, g is interpreted as a pointer to a function that takes
an int argument and that returns an int.
You can use a trailing return type in the declaration or definition of a
pointer to a function. For example:
auto(*fp)()->int;
In this example, fp is a pointer to a function that returns int. You can
rewrite the declaration of fp without using a trailing return type as int
(*fp)(void).
Recursion
A process by which a function calls itself repeatedly
Either directly.
X calls X
Or cyclically in a chain.
X calls Y, and Y calls X
Used for repetitive computations in which each
action is stated in terms of a previous result
fact(n) = n * fact (n-1)
1
For a problem to be written in recursive form, two
conditions are to be satisfied:
It should be possible to express the problem in
recursive form
Solution of the problem in terms of solution of the same
problem on smaller sized data
The problem statement must include a
stopping/terminating condition
The direct solution of the problem for a small enough
size
Stopping/Terminating
fact(n) = 1, if n = 0
condition
= n * fact(n-1), if n > 0
Recursive definition
3
Examples:
Factorial:
fact(0) = 1
fact(n) = n * fact(n-1), if n > 0
GCD:
gcd (m, m) = m
gcd (m, n) = gcd (m%n, n), if m > n
gcd (m, n) = gcd (n, n%m), if m < n
Fibonacci series (1,1,2,3,5,8,13,21,….)
fib (0) = 1
fib (1) = 1
fib (n) = fib (n-1) + fib (n-2), if n > 1
4
Factorial
long int fact (int n)
{
if (n == 1)
return (1);
else
return (n * fact(n-1));
}
5
Factorial Execution
long int fact (int n)
{
if (n = = 1) return (1);
else return (n * fact(n-1));
}
6
Factorial Execution
fact(4)
long int fact (int n)
{
if (n = = 1) return (1);
else return (n * fact(n-1));
}
7
Factorial Execution
fact(4)
if (4 = = 1) return (1);
else return (4 * fact(3));
long int fact (int n)
{
if (n = = 1) return (1);
else return (n * fact(n-1));
}
8
Factorial Execution
fact(4)
if (4 = = 1) return (1);
else return (4 * fact(3));
if (3 = = 1) return (1);
else return (3 * fact(2));
long int fact (int n)
{
if (n = = 1) return (1);
else return (n * fact(n-1));
}
9
Factorial Execution
fact(4)
if (4 = = 1) return (1);
else return (4 * fact(3));
if (3 = = 1) return (1);
else return (3 * fact(2));
if (2 = = 1) return (1);
else return (2 * fact(1));
long int fact (int n)
{
if (n = = 1) return (1);
else return (n * fact(n-1));
}
10
Factorial Execution
fact(4)
if (4 = = 1) return (1);
else return (4 * fact(3));
if (3 = = 1) return (1);
else return (3 * fact(2));
if (2 = = 1) return (1);
else return (2 * fact(1));
long int fact (int n)
{ if (1 = = 1) return (1);
if (n = = 1) return (1);
else return (n * fact(n-1));
}
11
Factorial Execution
fact(4)
if (4 = = 1) return (1);
else return (4 * fact(3));
if (3 = = 1) return (1);
else return (3 * fact(2));
if (2 = = 1) return (1);
else return (2 * fact(1));
long int fact (int n)
{ if (1 = = 1) return (1);
if (n = = 1) return (1);
else return (n * fact(n-1));
}
12
Factorial Execution
fact(4)
if (4 = = 1) return (1);
else return (4 * fact(3));
if (3 = = 1) return (1);
else return (3 * fact(2)); 2
if (2 = = 1) return (1);
else return (2 * fact(1));
long int fact (int n)
{
if (1 = = 1) return (1);
if (n = = 1) return (1);
else return (n * fact(n-1));
}
13
Factorial Execution
fact(4)
if (4 = = 1) return (1);
else return (4 * fact(3)); 6
if (3 = = 1) return (1);
else return (3 * fact(2)); 2
if (2 = = 1) return (1);
else return (2 * fact(1));
long int fact (int n)
{
if (1 = = 1) return (1);
if (n = = 1) return (1);
else return (n * fact(n-1));
}
14
Factorial Execution
fact(4) 24
if (4 = = 1) return (1);
else return (4 * fact(3)); 6
if (3 = = 1) return (1);
else return (3 * fact(2)); 2
if (2 = = 1) return (1);
else return (2 * fact(1));
long int fact (int n)
{
if (1 = = 1) return (1);
if (n = = 1) return (1);
else return (n * fact(n-1));
}
15
Example: Finding max in an array
int findMax(int A[ ], int n) Terminating condition. Small
{ size problem that you know
int temp; how to solve directly without
calling any functions
if (n==1)
{
return A[0];
} Recursive call. Find the max
temp = findMax(A, n-1); in the first n-1 elements
(exact same problem, just
if (A[n-1] > temp)
solved on a smaller array).
return A[n-1];
else return temp;
}
Important things to remember
Think how the whole problem (finding max of n
elements in A) can be solved if you can solve the
exact same problem on a smaller problem (finding
max of first n-1 elements of the array). But then, do
NOT think how the smaller problem will be solved,
just call the function recursively and assume it will
be solved.
When you write a recursive function
First write the terminating/base condition
Then write the rest of the function
Always double-check that you have both
Back to Factorial: Look at the variable
addresses (a slightly different program) !
int main()
Output
{
int x,y; 4
scanf("%d",&x); F: data = 4, &data = 3221224528
y = fact(x); &val = 3221224516
printf ("M: x= %d, y = %d\n", x,y); F: data = 3, &data = 3221224480
return 0;
&val = 3221224468
}
int fact(int data) F: data = 2, &data = 3221224432
{ int val = 1; &val = 3221224420
printf("F: data = %d, &data = %u \n F: data = 1, &data = 3221224384
&val = %u\n", data, &data, &val); &val = 3221224372
if (data>1) val = data*fact(data-1);
M: x= 4, y = 24
return val;
18
}
The memory addresses for the variable data are
different in different calls!
They are not the same variable.
Each function call will have its own set of variables,
even if the name of the variable is the same as it is the
same function being called
Change made to one will not be seen by the calling
function on return
19
int main() 4 printf ("M: x= %d, y =
{ %d\n", x,y);return 0;
count = 1, data = 1
int x,y;
count = 1, data = 2
scanf("%d",&x); Output
count = 1, data = 3
y = fact(x);
} count = 1, data = 4
int fact(int data) M: x= 4, y = 24
{
int val = 1, count = 0;
if (data>1) val = data*fact(data-1); • Count did not change
count++;
even though ++ done!
• Each call does it on its
printf(“count = %d, data = %d\n”,
count, data); own copy, lost on return
return val; 20
}
Fibonacci Numbers
Fibonacci recurrence:
fib(n) = 1 if n = 0 or 1;
= fib(n – 2) + fib(n – 1)
otherwise;
int fib (int n){
if (n == 0 or n == 1)
return 1; [Base]
return fib(n-2) + fib(n-1) ;
[Recursive]
}
21
int fib (int n) {
if (n == 0 || n == 1) Fibonacci recurrence:
return 1; fib(n) = 1 if n = 0 or 1;
return fib(n-2) + fib(n-1) ;
} = fib(n – 2) + fib(n – 1)
otherwise;
fib (5)
fib (3) fib (4)
fib (1) fib (2) fib (2) fib (3)
fib (0) fib (1) fib (0) fib (1) fib (1) fib (2)
fib (0) fib (1)
22
int fib (int n) {
if (n == 0 || n == 1) Fibonacci recurrence:
return 1; fib(n) = 1 if n = 0 or 1;
return fib(n-2) + fib(n-1) ;
} = fib(n – 2) + fib(n – 1)
otherwise;
fib (5)
fib (3) fib (4)
fib (1) fib (2) fib (2) fib (3)
1
fib (0) fib (1) fib (0) fib (1) fib (1) fib (2)
1 1 1 1 1
fib (0) fib (1)
1 1
fib.c 23
int fib (int n) {
if (n==0 || n==1) Fibonacci recurrence:
return 1; fib(n) = 1 if n = 0 or 1;
return fib(n-2) + fib(n-1) ;
} = fib(n – 2) + fib(n – 1)
8 otherwise;
fib (5)
3 5
fib (3) fib (4)
1 2 2 3
fib (1) fib (2) fib (2) fib (3)
1 2
1 1 1 1 1
fib (0) fib (1) fib (0) fib (1) fib (1) fib (2)
1 1 1 1 1 1
1
fib (0) fib (1)
24