Function Pointers with typedef - Method 1

In this section, you are going to learn

  • Step 1 : Define function type

typedef return_type function_type (parameters_list);
  • Step 2 : Define function Pointer using function type

function_type *fp;
  • Step 3 : Assing address of a function to fp

fp = funx;
  • Step 4 : Call the function using fp

fp(); // This is equal to funx()
  • 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 function type

    typedef int fp(int, int);
    
    • Step 2 : Define function Pointer using function type

    fp *calc;
    
    • Step 3 : 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 4 : Assign function pointer with address of an actual function

    calc = sum;
    

    OR

    calc = &sum;
    
    • Step 5 : 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
 4typedef int fp(int, int);
 5
 6// Step 2 : Define function Pointer using function type
 7fp *calc;
 8
 9// Step 3 : Define a function
10int sum(int a, int b)
11{
12        return a + b;
13}
14
15int main(void)
16{
17        int s;
18
19        // Step 4 : Assign function pointer with address of an actual function
20        calc = sum;
21
22        // Step 5 : Use the function pointer to call the function
23        s = calc(5, 6);
24
25        printf("sum = %d\n", s);
26
27        return 0;
28}
  • 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 fp for above function

  • Step 3 : Define a function fy() taking function pointer fp as an arguement

  • Step 4 : Call the function fx() using function pointer fp inside fy()

  • Step 5 : Call the function fy() by passing fx as argument

  • Step 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 fp for above function

typedef void fp(void);

fp *fptr;
  • Step 3 : Define a function fy() taking function pointer fp as an arguement

void fy(fp *fptr)
{
}
  • Step 4 : Call the function fx() using function pointer fp inside fy()

void fy(fp *fptr)
{
        fptr();
}
  • Step 5 : Call the function fy() by passing fx as argument

fy(fx);
  • See full program below

 1#include <stdio.h>
 2
 3typedef void fp(void);
 4
 5void fx(void)
 6{
 7        printf("Inside function fx()\n");
 8}
 9
10void fy(fp *fptr)
11{
12        fptr();
13}
14
15int main(void)
16{
17        fy(fx);
18
19        return 0;
20}
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()

typedef int fp(int, int);

fp *calc;
  • In this example, calc is the function pointer

  • return type of calc is int. Because return type of sum and sub is int

  • Number of parameters of calc is two. Because Number of parameters of sum and sub is two

  • Type of first parameter is int. Because type of first parameter is int in sum and sub

  • Type of second parameter is int. Because type of second parameter is int in sum and sub

  • Step 3 : Define a function do_calculation() taking function pointer calc as an arguement

int do_calculation(fp *calc, int a, int b)
{
}
  • do_calculation takes 3 arguements

  • First is function pointer calc

  • Second is integer a

  • Third is integer b

  • Step 4 : Call the function pointer calc inside do_calculation

int do_calculation(fp *calc, int a, int b)
{
        return calc(a, b);
}
  • calc is a function pointer which can hold the address of any function whose prototype matches with that of calc

  • Step 5 : Call the function do_calculation() by passing sum or sub as argument

  • While calling do_calculation(), pass 3 arguements

  • First : Address of a function whose prototype matches with that of calc

  • Second : integer

  • Third : integer

  • See full program below

  • Function do_calculation is called first time to perform addition using sum

  • Function do_calculation is called second time to perform subtraction using sub

  • In both cases, definition of function do_calculation is common !

 1#include <stdio.h>
 2
 3typedef int fp(int, int);
 4
 5int sum(int a, int b)
 6{
 7        return a + b;
 8}
 9
10int sub(int a, int b)
11{
12        return a - b;
13}
14
15int do_calculation(fp *calc, int a, int b)
16{
17        return calc(a, b);
18}
19
20int main(void)
21{
22        int s;
23
24        s = do_calculation(sum, 5, 6);
25
26        printf("sum = %d\n", s);
27
28        s = do_calculation(sub, 5, 6);
29
30        printf("sub = %d\n", s);
31
32        return 0;
33}
1sum = 11
2sub = -1
  • In this section, you are going to learn

Functions returning function pointers

  • Step 1 : Define a function fx

    void fx(void)
    {
            printf("Inside function fx()\n");
    }
    
  • Step 2 : Identify the function pointer prototype for function fx

    typedef void fp(void);
    
  • Step 2 : Define a function get_fx_operation which returns function pointer

    fp * get_fx_operation(void)
    {
            return fx;
    }
    

    Note the syntax !

  • Step 3 : Call get_fx_operation and store the return value in function pointer fx_p

    fx_p = get_fx_operation();
    

    Where the prototype of fx_p should match with prototype of fx()

    fp *fx_p;
    
  • Step 4 : Call the function using fx_p

    fx_p(); // This calls function fx()
    
  • Step 5 : See the full program below

 1#include <stdio.h>
 2
 3typedef void fp(void);
 4
 5void fx(void)
 6{
 7        printf("Inside function fx()\n");
 8}
 9
10fp * get_fx_operation(void)
11{
12        return fx;
13}
14
15int main(void)
16{
17        fp *fx_p;
18
19        fx_p = get_fx_operation();
20
21        fx_p();  // This calls function fx()
22
23        return 0;
24}

In this example, program decides the sorting mechanism to be used at run time based on the array size

  • Step 1 : Define two sorting algorithm functions

void insertion_sort(int *arr, int n)
{
}

void selection_sort(int *arr, int n)
{
}
  • Step 2 : Define function pointer type for above functions

typedef void sort_fp(int *arr, int n)
  • Step 3 : get_sort_method returns sorting method to be used based on array size

sort_fp * get_sort_method(int n)
{
        if (n <= 2)
                return insertion_sort;
        else
                return selection_sort;
}
  • Step 4 : analyse_data calls get_sort_method function to sort

void analyse_data(int *arr, int n)
{
        sort_fp *sort_fptr;

        sort_fptr = get_sort_method(n);

        sort_fptr(arr, n);
}
  • Step 5 : What is the advantage ?

  • Whenever the array size changes the function analyse_data need not change !

  • If analyse_data is defined in a seprate x.c file, we need not recompile x.c

  • In real time, analyse_data can be very big function with calls to many function pointers

  • Step 4 : See the full program below

 1#include <stdio.h>
 2
 3typedef void sort_fp(int *arr, int n);
 4
 5int arr[] = { 47, 13, 63, 29, 7 };
 6
 7void insertion_sort(int *arr, int n)
 8{
 9}
10
11void selection_sort(int *arr, int n)
12{
13}
14
15sort_fp * get_sort_method(int n)
16{
17        if (n <= 2)
18                return insertion_sort;
19        else
20                return selection_sort;
21}
22
23void analyse_data(int *arr, int n)
24{
25        sort_fp *sort_fptr;
26
27        sort_fptr = get_sort_method(n);
28
29        sort_fptr(arr, n);
30}
31
32int main(void)
33{
34        analyse_data(arr, sizeof(arr) / sizeof(arr[0]) );
35
36        return 0;
37}
  • Step 1 : Define a function pointer type fp

    typedef void fp_param(int);
    
    typedef void fp_return(void);
    
  • Step 1 : Define a function get_fx_operation which takes function pointer as arguement and returns a function pointer

    • get_fx_operation is written using concepts from Example 2 and Example 3

    • get_fx_operation takes fs_p as arguement which is a function pointer which can hold the address of a function which returns void and takes int as an arguement

    • get_fx_operation returns fx or gx depending on the value of a

fp_return * get_fx_operation( fp_param * fs_p )
{
        int a = 5;

        fs_p(a);

        if (a > 0)
                return fx;
        else
                return gx;
}
  • Step 2 : Call get_fx_operation and pass address of a function

    • We are passing address of sample_fun as arguement to get_fx_operation

fx_p = get_fx_operation(sample_fun);
  • Step 3 : See the full program below

 1#include <stdio.h>
 2
 3typedef void fp_param(int);
 4
 5typedef void fp_return(void);
 6
 7void fx(void)
 8{
 9        printf("Inside function fx() : Positive\n");
10}
11
12void gx(void)
13{
14        printf("Inside function gx() : Negative\n");
15}
16
17void sample_fun(int a)
18{
19        printf("a = %d \n", a);
20}
21
22fp_return * get_fx_operation( fp_param * fs_p )
23{
24        int a = 5;
25
26        fs_p(a);
27
28        if (a > 0)
29                return fx;
30        else
31                return gx;
32}
33
34int main(void)
35{
36        fp_return *fx_p;
37
38        fx_p = get_fx_operation(sample_fun);
39
40        fx_p();  // This calls function fx()
41
42        return 0;
43}
  • Similar functions can be grouped into an array

  • We call this as array of function pointers

  • Array of function pointers enables asynchronous event handling

typedef return_type function_type (parameters_list);

function_type *fp_arr[] = {functions_list};
  • Step 1 : Define an array of function pointers

    • calc is an array of function pointers

    • Each element in this array is a function which takes two integers as argement and returns void

typedef void fp(int, int);

fp *calc[] = { 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
18typedef void fp(int, int);
19
20fp *calc[] = { sum, sub, mul };
21
22int main(void)
23{
24        for (int i = 0; i < sizeof(calc)/sizeof(calc[0]); i++)
25        {
26                calc[i](5, 6);
27        }
28
29        return 0;
30}
  • Output is as below

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

typedef void fp(void);

fp *ev_cb[] = {
        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
32typedef void fp(void);
33
34fp *ev_cb[] = {
35        ev_connect_cb,
36        ev_disconnect_cb,
37        ev_reconnect_cb,
38        };
39
40void generate_events()
41{
42        int i;
43        for (;;) {
44                for (i = 0; i < EV_MAX; i++) {
45                        int ev_id = (rand() %
46                        (EV_MAX - EV_INIT + 1)) + EV_INIT;
47                        handle_event(ev_id);
48                }
49        }
50}
51
52void handle_event(int ev_id)
53{
54        ev_cb[ev_id]();
55}
56
57int main(void)
58{
59        generate_events();
60        return 0;
61}
  • 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

typedef int fp(struct student_db *s);

struct student_db
{
        int id;
        int age;
        int marks;
        char name[32];

        fp *get_age_p;
        fp *get_marks_p;
};

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
 5typedef int fp(struct student_db *s);
 6
 7struct student_db
 8{
 9        int id;
10        int age;
11        int marks;
12        char name[32];
13
14        fp *get_age_p;
15        fp *get_marks_p;
16};
17
18int get_age(struct student_db *s)
19{
20        return s->age;
21}
22
23int get_marks(struct student_db *s)
24{
25        return s->marks;
26}
27
28int main(void)
29{
30        struct student_db s1 = {
31        .id = 101,
32        .age = 20,
33        .marks = 97,
34        .name = "Adam",
35        .get_age_p = get_age,
36        .get_marks_p = get_marks
37        };
38
39        struct student_db s2 = {
40        .id = 102,
41        .age = 21,
42        .marks = 98,
43        .name = "Ram",
44        .get_age_p = get_age,
45        .get_marks_p = get_marks
46        };
47
48        printf("Age of s1 = %d\n", s1.get_age_p(&s1));
49        printf("Marks of s1 = %d\n", s1.get_marks_p(&s1));
50
51        printf("Age of s2 = %d\n", s2.get_age_p(&s2));
52        printf("Marks of s2 = %d\n", s2.get_marks_p(&s2));
53
54        return 0;
55}

Simple function Pointer : Method 1

typedef return_type fun (parameter_list);

Basic Function Pointer syntax

fun *fp;

fp = function;

fp is assigned with address of function

fp();

fp() is equal to function()

Simple function Pointer : Method 2

typedef return_type fun (parameter_list);

Basic Function Pointer syntax

fun *fp;

fp = &function;

fp` is assigned with address of function

(*fp) ();

(*fp) () is equal to function()

Array of function Pointers

typedef return_type fun (parameter_list);

Basic Array of Function Pointers syntax

fun *fp[];

fp[0] = funx, fp[1] = funy

function pointers fp[0] and fp[1] are initialised

fp[0]()

fp[0]() is equal to funx()

fp[1]()

fp[1]() is equal to funy()