Function Pointers without typedef
In this chapter, you are going to learn
Uses of funcion pointers ?
Topics in this section,
Section 2 : Functions taking function pointers as an arguement
Section 3.3 : Function returns a function which returns a function which returns a function pointer
Section 4 : Function taking function pointers as an arguement and returning function pointers
Section 5.1 : Array of function pointers to implement calculator
Section 5.2 : Array of Function Pointers for handling asynchronous events
return_type (*function_pointer)(parameters_list);
In this program,
Function sum() returns sum of two integers
1#include <stdio.h>
2
3int sum(int a, int b)
4{
5 return a + b;
6}
7
8int main(void)
9{
10 int s;
11
12 s = sum(5, 6);
13
14 printf("sum = %d\n", s);
15
16 return 0;
17}
Now let us replace call to function sum() using function pointer
Step 1 : Define a function pointer
int (*calc)(int, int);
Step 2 : Define a function
int sum(int a, int b) { return a + b; }
Note that, return type and function parameters of function pointer should match with that of actual function
Step 3 : Assign function pointer with address of an actual function
calc = sum;
OR
calc = ∑
Step 4 : Use the function pointer to call the function
s = calc(5, 6);
OR
s = (*calc)(5, 6);
See full program below
1#include <stdio.h>
2
3// Step 1 : Define a function pointer
4int (*calc)(int, int);
5
6// Step 2 : Define a function
7int sum(int a, int b)
8{
9 return a + b;
10}
11
12int main(void)
13{
14 int s;
15
16 // Step 3 : Assign function pointer with address of an actual function
17 calc = sum;
18
19 // Step 4 : Use the function pointer to call the function
20 s = calc(5, 6);
21
22 printf("sum = %d\n", s);
23
24 return 0;
25}
In this section, you are going to learn
Functions taking function pointers as an arguement
Step 1 : Define a function called
fx()Step 2 : Identify the function pointer prototype
fpfor above functionStep 3 : Define a function
fy()taking function pointerfpas an arguementStep 4 : Call the function
fx()using function pointerfpinsidefy()Step 5 : Call the function
fy()by passingfxas argumentStep 6 : Let us see few examples
Step 1 : Define a function called
fx()
void fx(void)
{
printf("Inside function fx()\n");
}
Step 2 : Identify the function pointer prototype
fpfor above function
void (*fp)(void)
Step 3 : Define a function
fy()taking function pointerfpas an arguement
void fy(void (*fp)(void))
{
}
Step 4 : Call the function
fx()using function pointerfpinsidefy()
void fy(void (*fp)(void))
{
fp();
}
Step 5 : Call the function
fy()by passingfxas argument
fy(fx);
See full program below
1#include <stdio.h>
2
3void fx(void)
4{
5 printf("Inside function fx()\n");
6}
7
8void fy(void (*fp)(void))
9{
10 fp();
11}
12
13int main(void)
14{
15 fy(fx);
16
17 return 0;
18}
Inside function fx()
Step 1 : Define two functions
sum(),sub()
int sum(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
Note that, Prototypes of sum() and sub() are matching
Step 2 : Identify the function pointer prototype for functions
sum(),sub()
int (*calc)(int, int)
In this example,
calcis the function pointerreturn type of
calcisint. Because return type ofsumandsubisintNumber of parameters of
calcis two. Because Number of parameters ofsumandsubis twoType of first parameter is
int. Because type of first parameter isintinsumandsubType of second parameter is
int. Because type of second parameter isintinsumandsub
Step 3 : Define a function
do_calculation()taking function pointercalcas an arguement
int do_calculation(int (*calc)(int, int), int a, int b)
{
}
do_calculationtakes 3 arguementsFirst is function pointer
calcSecond is integer
aThird is integer
b
Step 4 : Call the function pointer
calcinsidedo_calculation
int do_calculation(int (*calc)(int, int), int a, int b)
{
return calc(a, b);
}
calcis a function pointer which can hold the address of any function whose prototype matches with that ofcalc
Step 5 : Call the function
do_calculation()by passingsumorsubas argument
While calling
do_calculation(), pass 3 arguementsFirst : Address of a function whose prototype matches with that of
calcSecond : integer
Third : integer
See full program below
Function
do_calculationis called first time to perform addition usingsumFunction
do_calculationis called second time to perform subtraction usingsubIn both cases, definition of function
do_calculationis common !
1#include <stdio.h>
2
3int sum(int a, int b)
4{
5 return a + b;
6}
7
8int sub(int a, int b)
9{
10 return a - b;
11}
12
13int do_calculation(int (*calc)(int, int), int a, int b)
14{
15 return calc(a, b);
16}
17
18int main(void)
19{
20 int s;
21
22 s = do_calculation(sum, 5, 6);
23
24 printf("sum = %d\n", s);
25
26 s = do_calculation(sub, 5, 6);
27
28 printf("sub = %d\n", s);
29
30 return 0;
31}
1sum = 11
2sub = -1
In this section, you are going to learn
Functions returning function pointers
Step 1 : Define a function
fxvoid fx(void) { printf("Inside function fx()\n"); }
Step 2 : Define a function
get_fx_operationwhich returns function pointervoid (* get_fx_operation(void) ) (void) { return fx; }
Note the syntax !
Step 2.1 : Write the prototype of function pointer
void (*) (void) { }
Step 2.2 : Write the function name and its arguements
void (* get_fx_operation(void) ) (void) { }
Step 2.3 : Return the address of a function
void (* get_fx_operation(void) ) (void) { return fx; }
Step 3 : Call
get_fx_operationand store the return value in function pointerfx_pfx_p = get_fx_operation();
Where the prototype of
fx_pshould match with prototype offx()void (*fx_p)(void);
Step 4 : Call the function using
fx_pfx_p(); // This calls function fx()
Step 5 : See the full program below
1#include <stdio.h>
2
3void fx(void)
4{
5 printf("Inside function fx()\n");
6}
7
8void (* get_fx_operation(void) ) (void)
9{
10 return fx;
11}
12
13int main(void)
14{
15 void (*fx_p)(void);
16
17 fx_p = get_fx_operation();
18
19 fx_p(); // This calls function fx()
20
21 return 0;
22}
In this example, program decides the sorting mechanism to be used at run time based on the array size
Step 1 :
get_sort_methodreturns sorting method to be used based on array size
void ( *get_sort_method(int n) ) (int *, int n)
{
if (n <= 2)
return insertion_sort;
else
return selection_sort;
}
Step 2 :
analyse_datacallsget_sort_methodfunction to sort
void analyse_data(int *arr, int n)
{
void (*sort_fp)(int *arr, int n);
sort_fp = get_sort_method(n);
sort_fp(arr, n);
}
Step 3 : What is the advantage ?
Whenever the array size changes the function
analyse_dataneed not change !If
analyse_datais defined in a sepratex.cfile, we need not recompilex.c
In real time,
analyse_datacan be very big function with calls to many function pointers
Step 4 : See the full program below
1#include <stdio.h>
2
3int arr[] = { 47, 13, 63, 29, 7 };
4
5void insertion_sort(int *arr, int n)
6{
7}
8
9void selection_sort(int *arr, int n)
10{
11}
12
13void ( *get_sort_method(int n) ) (int *, int n)
14{
15 if (n <= 2)
16 return insertion_sort;
17 else
18 return selection_sort;
19}
20
21void analyse_data(int *arr, int n)
22{
23 void (*sort_fp)(int *arr, int n);
24
25 sort_fp = get_sort_method(n);
26
27 sort_fp(arr, n);
28}
29
30int main(void)
31{
32 analyse_data(arr, sizeof(arr) / sizeof(arr[0]) );
33
34 return 0;
35}
Can you guess what is happening in below program ?
1#include <stdio.h>
2
3int fa(void)
4{
5 printf("Inside function fa\n");
6 return 0;
7}
8
9int (* funx(void) ) (void)
10{
11 return fa;
12}
13
14int (*(* funy(void)) (void)) (void)
15{
16 return funx;
17}
18
19int (*(*(* funz(void)) (void)) (void)) (void)
20{
21 return funy;
22}
23
24int main(void)
25{
26 funz()()()();
27 return 0;
28}
Step 1 : Define a function
get_fx_operationwhich takes function pointer as arguement and returns a function pointerget_fx_operationis written using concepts from Section 2 and Section 3get_fx_operationtakesfs_pas arguement which is a function pointer which can hold the address of a function which returnsvoidand takesintas an arguementget_fx_operationreturnsfxorgxdepending on the value ofa
void (* get_fx_operation( void (*fs_p)(int) ) ) (void)
{
int a = 5;
fs_p(a);
if (a > 0)
return fx;
else
return gx;
}
Step 2 : Call
get_fx_operationand pass address of a functionWe are passing address of
sample_funas arguement toget_fx_operation
fx_p = get_fx_operation(sample_fun);
Step 3 : See the full program below
1#include <stdio.h>
2
3void fx(void)
4{
5 printf("Inside function fx() : Positive\n");
6}
7
8void gx(void)
9{
10 printf("Inside function gx() : Negative\n");
11}
12
13void sample_fun(int a)
14{
15 printf("a = %d \n", a);
16}
17
18void (* get_fx_operation( void (*fs_p)(int) ) ) (void)
19{
20 int a = 5;
21
22 fs_p(a);
23
24 if (a > 0)
25 return fx;
26 else
27 return gx;
28}
29
30int main(void)
31{
32 void (*fx_p)(void);
33
34 fx_p = get_fx_operation(sample_fun);
35
36 fx_p(); // This calls function fx()
37
38 return 0;
39}
Similar functions can be grouped into an array
We call this as array of function pointers
Array of function pointers enables asynchronous event handling
return_type ( *fp_array [ ] ) ( parameter_list ) = { functions_list };
Step 1 : Define an array of function pointers
calcis an array of function pointersEach element in this array is a function which takes two integers as argement and returns void
void ( *calc [ ] )( int, int ) = { sum, sub, mul };
Step 2 : Find number of elements in an array generic way
Number of elements in Array = Sizeof_Array / Size of One element
Number of elements in calc = sizeof(calc) / sizeof(calc[0])
Step 3 : Call the functions using array of function pointers
calc[i](5, 6);
// calc[0](5, 6) equals sum(5, 6)
// calc[1](5, 6) equals sub(5, 6)
// calc[2](5, 6) equals mul(5, 6)
Step 4 : See full program below
1#include <stdio.h>
2
3void sum(int a, int b)
4{
5 printf("Function sum called : a = %d, b = %d, sum = %d\n", a, b, a + b);
6}
7
8void sub(int a, int b)
9{
10 printf("Function sub called : a = %d, b = %d, sub = %d\n", a, b, a - b);
11}
12
13void mul(int a, int b)
14{
15 printf("Function mul called : a = %d, b = %d, mul = %d\n", a, b, a * b);
16}
17
18void (*calc[])(int, int) = { sum, sub, mul};
19
20int main(void)
21{
22 printf("size of array = %ld\n", sizeof(calc));
23 printf("size of one element = %ld\n", sizeof(calc[0]));
24 printf("Number of elements in array = %ld\n", sizeof(calc)/sizeof(calc[0]));
25
26 for (int i = 0; i < sizeof(calc)/sizeof(calc[0]); i++)
27 {
28 calc[i](5, 6);
29 }
30
31 return 0;
32}
Output is as below
size of array = 24
size of one element = 8
Number of elements in array = 3
Function sum called : a = 5, b = 6, sum = 11
Function sub called : a = 5, b = 6, sub = -1
Function mul called : a = 5, b = 6, mul = 30
Asynchoronous events - Can arrive at any time
In below example, events are generated randomly and handled dynamically
Step 1 : Define functions which handle specific events
void ev_connect_cb(void)
{
printf("Handled ev_connect_cb\n");
}
void ev_disconnect_cb(void)
{
printf("Handled ev_disconnect_cb\n");
}
void ev_reconnect_cb(void)
{
printf("Handled ev_reconnect_cb\n");
}
Step 2 : Map these functions to array of function pointers
void (*ev_cb[]) (void) = {
ev_connect_cb,
ev_disconnect_cb,
ev_reconnect_cb,
};
Step 3 : Call these functions based on event generated
ev_cb[ev_id]();
Step 4 : See full program below
1#include <stdio.h>
2#include <stdlib.h>
3#include <time.h>
4#include <unistd.h>
5
6void handle_event(int ev_id);
7
8enum events
9{
10 EV_INIT,
11 EV_CONNECT = EV_INIT,
12 EV_DISCONNECT,
13 EV_RECONNECT,
14 EV_MAX = EV_RECONNECT
15};
16
17void ev_connect_cb(void)
18{
19 printf("Handled ev_connect_cb\n");
20}
21
22void ev_disconnect_cb(void)
23{
24 printf("Handled ev_disconnect_cb\n");
25}
26
27void ev_reconnect_cb(void)
28{
29 printf("Handled ev_reconnect_cb\n");
30}
31
32void (*ev_cb[]) (void) = {
33 ev_connect_cb,
34 ev_disconnect_cb,
35 ev_reconnect_cb,
36 };
37
38void generate_events()
39{
40 int i;
41 for (;;) {
42 for (i = 0; i < EV_MAX; i++) {
43 int ev_id = (rand() %
44 (EV_MAX - EV_INIT + 1)) + EV_INIT;
45 handle_event(ev_id);
46 }
47 }
48}
49
50void handle_event(int ev_id)
51{
52 ev_cb[ev_id]();
53}
54
55int main(void)
56{
57 generate_events();
58 return 0;
59}
C language allows programmer to define function pointers inside a structure
After all, function pointer is another variable
Step 1 : Declare function pointers inside a structure
struct student_db
{
int id;
int age;
int marks;
char name[32];
int (*get_age_p) (struct student_db *s);
int (*get_marks_p)(struct student_db *s);
};
get_age_p is a function pointer
get_marks_p is a function pointer
Step 2 : Assign function pointers with actual function definitions at the time of structure object creation
struct student_db s1 = {
.id = 101,
.age = 20,
.marks = 97,
.name = "Adam",
.get_age_p = get_age,
.get_marks_p = get_marks
};
Step 3 : Call the function via function pointers using structure object
s1.get_age_p(&s1);
Step 4 : See full program below
1#include <stdio.h>
2
3struct student_db
4{
5 int id;
6 int age;
7 int marks;
8 char name[32];
9
10 int (*get_age_p) (struct student_db *s);
11 int (*get_marks_p)(struct student_db *s);
12};
13
14int get_age(struct student_db *s)
15{
16 return s->age;
17}
18
19int get_marks(struct student_db *s)
20{
21 return s->marks;
22}
23
24int main(void)
25{
26 struct student_db s1 = {
27 .id = 101,
28 .age = 20,
29 .marks = 97,
30 .name = "Adam",
31 .get_age_p = get_age,
32 .get_marks_p = get_marks
33 };
34
35 struct student_db s2 = {
36 .id = 102,
37 .age = 21,
38 .marks = 98,
39 .name = "Ram",
40 .get_age_p = get_age,
41 .get_marks_p = get_marks
42 };
43
44 printf("Age of s1 = %d\n", s1.get_age_p(&s1));
45 printf("Marks of s1 = %d\n", s1.get_marks_p(&s1));
46
47 printf("Age of s2 = %d\n", s2.get_age_p(&s2));
48 printf("Marks of s2 = %d\n", s2.get_marks_p(&s2));
49
50 return 0;
51}
Simple function Pointer : Method 1 |
|
|---|---|
return_type (*fp) (parameter_list); |
Basic Function Pointer syntax |
fp = function; |
|
fp(); |
|
Simple function Pointer : Method 2 |
|
|---|---|
return_type (*fp) (parameter_list); |
Basic Function Pointer syntax |
fp = &function; |
fp` is assigned with address of |
(*fp) (); |
|
Array of function Pointers |
|
|---|---|
return_type (*fp [ ] ) (parameter_list); |
Basic Array of Function Pointers syntax |
fp[0] = funx, fp[1] = funy |
function pointers fp[0] and fp[1] are initialised |
fp[0]() |
|
fp[1]() |
|
Current Module
Previous Module
Next Module
Other Modules