Chapter:C function pointers

From Juneday education
Jump to: navigation, search

Function pointers in C and C++

Why function pointers anyway? In C (C++) you can use function pointers to implement plugins or to change, at one place, the function to call, no matter where you use the function (through the pointer), or to remove “expensive” if statements in tight loops.

Videos

C - Function Pointer (Full playlist) | C - Function pointers 2/2 | C - Function pointers 1/2 | Function pointers (PDF)

Getting started

But instead of spending too much energy on talking we’ll continue with an example. Throughout this introduction we’ll use a feedback functionality. Your program wants to give feedback to the user and instead of using a variable which we switch over to choose the right feedback implementation we are going to use function pointers. Depending on what environment the user is using we can use a gui feedback or console based feedback. Later on, in introduction to writing plugins, we’ll dive into more practical use of them pointers.

Let’s settle for a feedback function prototype (stripped down functionality, no variable sized argument list etc):

int default_feedback(const char *str)

The function returns an int. The first argument is the string to print. Let’s add an implementation to the function:

int default_feedback(char *str)
{
  return fprintf(stdout, "%s", str);
}

Please note, we haven’t used function pointers yet. We can use the function by calling it like this:

 default_feedback("Ordinary call\n");

So far so good. Let’s define our first function pointer. Let’s create a variable feedback_fun that stores the pointer to the function we want to call.

int (*feedback_fun)(const char *str) ;

We can see that this looks a bit like the function above. We’ve just added some “(*” and an extra “)”. What the live above says is: the function pointed to by feedback_fun returns an int and takes char *str as argument. Piece of cake, isn’t it? We can now use the variable to store the address to a function we want to use.

Let’s store the address in our function pointer:

feedback_fun = default_feedback ;

and call the function through the function pointer

feedback_fun("Called using function pointer call\n");

Short example

Was that it? Yes, neat isn’t it? So if we turn this into a program, including a main function and some comments in one c file, we get this:

fp.c

The source code below is also available at: https://github.com/progund/programming-with-c/blob/master/function-pointers/fp.c.

/*
 * Copyright (c) 2018, Henrik Sandklef, Rikard Fröberg
 *
 */
#include <stdio.h>

/*
 * Global varible poiting to th feedback function choosen
 *
 */
int (*feedback_fun)(const char *str) ;


/*
 * Name:         default_feedback
 * Args:         str - string to print
 * Description:  Prints a string to given file
 */
int
default_feedback(const char *str)
{
  return fprintf(stderr, "[%s] %s", __func__, str);
}




int main(void)
{
  /* Set feedback_fun to point at default feedback function */
  feedback_fun = default_feedback ;

  /* Call the  default_feedback in the ordinary way */
  printf ("Calling the function the usual way\n");
  default_feedback("Ordinary call\n");

  /* Call the default_feedback through the feedback_fun variable */
  printf ("Calling the function via the function pointer\n");
  feedback_fun("Called using function pointer call\n");
  return 0;
}

Easier syntax using typedef

There’s a trick make life a bit easier when dealing with function pointers. We can typedef the function. In the previous article we used a feedback function. Let’s take it from there.

We prototyped our feedback function like this:

int (*feedback_fun)(const char *str) ;

Instead we can create a new type of function like the above by using typedef like this:

typedef int (*feedback_ptr)(const char *str);

Doing this we can make the function declarations look nicer. We can declare a variable holding a pointer to the feedback functions like this:

feedback_ptr feedback_fun ;

Let's use a header file and one c file to make this code look a bit more worthy.

typedef-fp.h

#ifndef TYPEDEF_FP_H
#define TYPEDEF_FP_H

typedef int (*feedback_ptr)(const char *str);

#endif /* TYPEDEF_FP_H */

Source code is available here as well: https://github.com/progund/programming-with-c/blob/master/function-pointers/typedef/typedef-fp.h

typedef-fp.c

/*
 * Copyright (c) 2018, Henrik Sandklef, Rikard Fröberg
 *
 */
#include <stdio.h>
#include "typedef-fp.h"

/*
 * Global varible poiting to th feedback function choosen
 *
 */
feedback_ptr feedback_fun ;


/*
 * Name:         default_feedback
 * Args:         str - string to print
 * Description:  Prints a string to given file
 */
int
default_feedback(const char *str)
{
  return fprintf(stderr, "[%s] %s", __func__, str);
}



int main(void)
{
  /* Set feedback_fun to point at default feedback function */
  feedback_fun = default_feedback ;

  /* Call the  default_feedback in the ordinary way */
  printf ("Calling the function the usual way\n");
  default_feedback("Ordinary call\n");

  /* Call the default_feedback through the feedback_fun variable */
  printf ("Calling the function via the function pointer\n");
  feedback_fun("Called using function pointer call\n");
  return 0;
}

Source code is available here as well: https://github.com/progund/programming-with-c/blob/master/function-pointers/typedef/typedef-fp.c


Nice isn’t it? But we haven’t won that much. We have to wait until we dive into plugins until we really see the benefits if this.