C Language

To share this page click on the buttons below;

Pointer to functions

Functions are stored in memory at a certain address, isn‘t it? That does mean we can have pointers to function. The concept of pointers to function might appear tough for a beginner because it is difficult to find simple examples in which this feature is meaningful.

Nevertheless function pointers might be really useful because they allow the possibility to change the behavior of our program depending on some conditions that are known only when the software runs. But probably the most straightforward example of the use of pointers to function is the concept of callback.

Just to give you the first idea of what callbacks are we can have a short look on graphical applications (the application with Buttons to click, Text Boxes to fill and so on, the ones you are using every day). To develop such applications you need what is commonly called graphical toolkit: this is essentially a library containing functions you can call to draw your own graphical application. Now, when you press a button in a graphical application very different things can happen depending on the application itself. How we can connect the event "the button has been pressed" with the actual implementation of what we want to happen to react to that event? Well the simplest effective way is through a callback. In practice any buttons (please be aware of the fact that this is a simplification, in reality things are more complex) has a pointer to a function, which is a sort of a plug you can use to connect the button click event with its own actual implementation. The trick is simple: you take the pointer to the function that belongs to a certain button and you make it to point to some function you developed, when the button recognizes the event button pressed it automatically calls your function using the pointer.

The big picture here is: a piece of "generic" software (i.e. that manages a set of common features, but can be used in different ways, like our "button") has to provide some mechanism to attach the user defined behavior. This piece of "generic" software is provided as a library and is developed independently from the application that uses it, but since this software is generic, it needs a way to be customized by any application is going to use that library. A callback (or a pointer to function, which is the same) can be used to achieve this purpose.

The word "callback" refers to the way this solution works: when the library wants to have access to some user defined function it only uses a placeholder (a pointer to function indeed), the user then "registers" the callback (i.e. it makes the pointer to function to point to an actual user defined function) and that function will be call back when needed by the library itself.

As you can probably imagine, this mechanism can be used in general to adapt an application to change its behavior during the execution depending on some conditions: in this case the pointer to a function is made to point to different functions depending on those conditions.

Anyway the most important concept I want to underline here is that pointer to function are a powerful mechanism to reuse common (and well tested) code in different situations, using the pointers to function to adapt its behavior to a particular situation. For an actual example of that I forward you to the C++ sort function.

Declaring a pointer to function

To declare a pointer to function you must provide: the returning type of the function that will be pointed by the pointer followed by an * (that is the usual pointer operator) enclosed into a pair of parenthesis (and it is this pair of parenthesis that identifies the pointer function and makes it different respect to a pointer to a variable), immediately after the * (always within the parenthesis) there is the name of the pointer and that is followed by the argument list of the function pointed by the pointer.

Some examples would probably help to clarify:

/* the pointer "func" can be used to point to a function taking no argument and returning a integer */
int (*func)(void);
/* the pointer "f" can be used to point to a function taking 2 arguments (the first one is an integer
   and the second one is a double) and returning nothing  */
void (*f)(int, double);
/* the pointer "myfunc" can be used to point to a function taking 2 arguments (a pointer to a double
   and an integer) and returning a double */
double *(*myfunc)(double *, int);

I think that all is pretty obvious as explained in the comments. A point that perhaps is worth to highlight is that a pointer to function can be used to point functions that are taking pointers as arguments or that are returning pointers. Probably however the important point here is that a different pointers have to be declared and used for each different signature of a function.

The pointer func, for example, can be used to point to every function that takes no argument and return an integer, but it cannot be used to point to a function with an integer as argument, event if the returning type is always an integer. The reason for that is that when a function call is performed the function return value and the function argument list are properly "stacked" to perform the the function call itself, so that the compiler must know the return value and the argument list in advance in order to perform the function call in the proper way (that will be the argument of a next chapter).

The address of a function

To obtain the address of a variable we use the operator & : that, put in front of a variable, returns the address of that variable. To obtain the address of a function the procedure is even simpler: the name of the function is the address of the function itself (there is no need for the ampersand operator).

The next trivial example is aimed to demonstrate how to get the address of a function and how to use the pointer (once it has been properly set up to a function) to perform the function call through the pointer.

#include <stdio.h>

int increment_by_one(int a);
int increment_by_five(int b);

int increment_by_one(int a) {
   printf("Increment by one is used\n");   
   return a + 1;
}

int increment_by_five(int b) {
   printf("Increment by five is used\n");
   return b + 5;
}


int main(void) {
   int num = 0;
   /* pointer to a function that takes an integer argument and returns an integer */
   int (*func)(int);

   func = increment_by_one;

   num = func(num);
   printf("Num = %i\n",num);

   func = increment_by_five;

   num = func(num);
   printf("Num = %i\n",num);

   return 0;
}

First the function pointer func is made to point to the function increment_by_one, i.e. the address of the function (the name of the function itself) is put into the func pointer. The very same happens next but now the pointer func is redirected to the function increment_by_five. In both cases a function call is made using the pointer to function and some output is printed to proof that the call is effective indeed.

A slightly more complex example

This time I am going to show you an example a little bit more complex than usual (although still trivial) that will help to introduce a lot of new concepts.

With this example we will build a small library to handle a textual menu. This is a simplified situation respect to the graphical "button" we talked at the beginning of this note, but it still keeps all the details of the callbacks we want to demonstrate.

What this example wants to show is how to build a generic library to handle a textual menu: this menu will be displayed on console and will be "programmable" in the same way a graphical button is. So what we want to do is to decouple the menu "logic" (i.e. the display of a menu caption, the display of the various menu item, the catching of the menu item selection and so on), from the menu "use" inside an application (i.e. setting the caption for the menu and the various items and actually using the menu).

The behavior of the menu is simple: it displays a caption and several options, then it asks for a choice. The choice is made pressing a key of the keyboard (and return). If the choice is correctly recognized a callback function is available, this callback is the function we want to execute when the menu item is selected.

The menu library has to provide the functions to set up all is needed to use the menu (caption, menu item) and a function to show and use the menu. This menu library will be contained into a C module: so a pair of file, one source file with extension .c and one header file with extension .h.

We will compile this simple module to be a library: a library is the binary compiled form of the module, it contains and makes available to other programs all the menu functions in a binary form, all you have to do to use the library is to include the header file in your application and link against the library (.lib) file.

That is exactly what happens when we use the printf function: we include the stdio.h header and we link against the standard C library (although this step is so common that is automatically performed by the compiler without the need of our instructions).

Then we will write an application that uses the functions contained into the library.

The primary goal of this example is to show how callback functions can be set up and used, but also to demonstrate how we can keep separate different implementations: a generic library and different applications that use the library and customize its behavior through function pointers. However I will use this example also to give you some taste of different concepts that will be fully developed only in object oriented programming languages, like C++.

The menu library

Here is the header file of the menu library module:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Function to initialize the library.
   It MUST be always called before any other function listed below 

   Return value:  
   - 0 if initialization is successfull
   - 1 if initialization fail                                      */
int menu_init(void);


/* Function to set the main caption of the menu 
   - 'caption' is the string containing the caption of the menu 
   - 'len' is the lenght of the 'caption' string  

   Return value:
   - 0 if the menu caption is correctly set up
   - 1 if the function fail
   */
int menu_set_caption(char *caption, unsigned int len);

/* Function to add a menu item to the menu 
   - 'key' is the associated character to be entered to select the menu item
      Remark the key 'x' cannot be used because it triggers the exit of the menu
   - 'desc' is the description of the item 
   - 'len' is the lenght of the description string 
   - 'fun' is the function to be called when the menu item is selected

   Return value:
   - 0 if the menu item is correctly set up
   - 1 if the function fail
   */
int menu_add_item(char key, char *desc, unsigned int len, void (*fun)(void));

/* Call this function in your application to use the menu */
int menu_function(void);

/* Call this function when your done with the menu 
   It MUST be called always to properly release any resource*/
int menu_clean_up(void);

It is heavily commented (a detailed description of each function is provided, this is a good and polite practice for header files) and so I will not describe what the functions do. I will however note some important points.

The header file contains all the include files required by the library. You could have put those include file also in source file, but this (although this would make a perfectly working module anyway) will not be a polite choice, because the user of the library would not be aware of what module your library is going to use. So a common good practice is to list all the required &#35include into the header file of the module and then include just that header file into the source module file (the .c one). Unless you want to keep things secret (i.e. you want to hide which modules your library is using).

The header file lists all the "public" functions, i.e. all the functions library the application can actually use. I used the word "public" because I want to underline some common good C programming practices that had evolved into the (more sophisticated) private, public, protected paradigm of C++. Anyway we put into the header file of the module the functions we want the user of our library is aware of, but our library will contain also other functions that will not be directly available for the user, those will be in some way "private" to the library itself.

The set of functions listed into the header file define the interface of our library (again the concept of interface is something that has been evolved in other languages in more standardized statements like the pure virtual functions of C++ or the interfaces of Java). The interface is the pact the library makes with the applications: as far as the interface does not change applications can continue to use different versions of the library also if the internal implementation has been changed (to correct problems or to improve performances for example).

Two functions in particular are quite common in every C library: an initialization function (the menu_init) and a clean up one (the menu_clean_up). Those are very important functions because they perform all the relevant operations to set up the library and to properly release all the resources used by the library. They must be called at the beginning and at the end, but C language does not have a mechanism to automatically call those functions and this often is the cause of malfunctions: it is for this reason that C++ will introduce the concept of constructors and distructors which have the very same purpose.

Here is the source file of the menu library module:

#include "menulib.h"

/* ------------------- 
 * private constants 
 * ------------------- */

#define MAX_MENU_ITEMS 10

/* private variables */
static char menu_key[MAX_MENU_ITEMS];
static char *menu_string[MAX_MENU_ITEMS];
static void (*menu_functions[MAX_MENU_ITEMS])(void);
static char *menu_caption;
static int menu_pos;

/* ------------------------------
 * private functions declaration 
 * ------------------------------ */
static void menu_print(void);
static char menu_get_cmd(void);

/* ---------------------------------
 * private functions implementation 
 * --------------------------------- */

/* -------------------------------------------------------------------------- */
static void menu_print(void) {
/* -------------------------------------------------------------------------- */
   int i = 0;
   if(menu_caption != NULL) {
      printf("\n%s\n", menu_caption);
   }
   printf(" -> press 'x' (and return): to exit\n");
   for(i = 0; i < MAX_MENU_ITEMS; i++) {
      if(menu_string[i] != NULL) {
         printf(" -> press \'%c\' (and return): %s\n", menu_key[i], menu_string[i] );
      }
   }
   printf("Please select >: ");
}

/* -------------------------------------------------------------------------- */
static char menu_get_cmd(void) {
/* -------------------------------------------------------------------------- */   
    char cmd[2] = {' ', ' '};

    while(cmd[1] != '\n') {
      cmd[0] = getchar();
      cmd[1] = getchar();
    }

    return cmd[0];
}

/* --------------------------------
 * public functions implementation 
 * -------------------------------- */

/* -------------------------------------------------------------------------- */
int menu_init(void) {
/* -------------------------------------------------------------------------- */   

   int i = 0;
   /* proper initialization of data structure */
   menu_pos = 0;
   menu_caption = NULL;
   for(i = 0; i < MAX_MENU_ITEMS; i++) {
      menu_key[i] = '.';
      menu_string[i] = NULL;
      menu_functions[i] = NULL;
   }
   return 0;
}

/* -------------------------------------------------------------------------- */
int menu_set_caption(char *caption, unsigned int len) {
/* -------------------------------------------------------------------------- */   
   int rv = 0;
   size_t size = (size_t)(len * sizeof(char) + 1);
   if(menu_caption != NULL) {
      free(menu_caption);
   }
   menu_caption = (char *)malloc(size);

   if(menu_caption != NULL) {
      memset(menu_caption,0x00,size);
      memcpy(menu_caption,caption, size - 1);
   }
   else {
      rv = 1;
   }
   return rv;
}

/* -------------------------------------------------------------------------- */
int menu_add_item(char key, char *desc, unsigned int len, void (*fun)(void)) {
/* -------------------------------------------------------------------------- */   
   int rv = 0;
   if(key != 'x') {
      size_t size = (size_t)(len * sizeof(char) + 1);
      if(menu_pos < MAX_MENU_ITEMS) {
         menu_string[menu_pos] = (char *)malloc(size);
         if(menu_string[menu_pos] != NULL) {
            memset(menu_string[menu_pos],0x00,size);
            memcpy(menu_string[menu_pos],desc, size - 1);
            menu_key[menu_pos] = key;
            menu_functions[menu_pos] = fun;
            menu_pos++;
         }
      }
      else {
         rv = 1;
      }
   }
   else {
      rv = 1;
   }
   return rv;
}

/* -------------------------------------------------------------------------- */
int menu_clean_up(void) {
/* -------------------------------------------------------------------------- */   
   int i = 0;
   if(menu_caption != NULL) {
      free(menu_caption);
      menu_caption = NULL;
   }
   for(i = 0; i < MAX_MENU_ITEMS; i++) {
      if(menu_string[i] != NULL) {
         free(menu_string[i]);
         menu_string[i] = NULL;
      }
      menu_functions[i] = NULL;
      menu_key[i] = '.';
   }
   return 0;
}

/* -------------------------------------------------------------------------- */
int menu_function(void) {
/* -------------------------------------------------------------------------- */
   int exit = 0;
   char c = '.';
   int i = 0;
   int executed = 0;

   while(!exit) {
      menu_print();
      c = menu_get_cmd();
      executed = 0;
      if(c == 'x') {
         executed = 1;
         exit = 1;
      }
      else {
         for(i = 0; i < MAX_MENU_ITEMS; i++) {
            if(c == menu_key[i]) {
               if(menu_functions[i] != NULL) {
                  menu_functions[i]();
                  executed = 1;
               }
            }
         }
      }
      if(!executed) {
         printf("Option not recognized or not available\n");
      }
   }
   return 0;
}

I will not go into the details of the implementation, because I prefer you to study the code and understand it by yourself as a little exercise. I will however provide you with some notes, as usual.

The source file only includes the header file of the module itself.

Again it comes back the concept of public and private: the source file declare and use some variables and some functions that are private to the module itself, only the library must have access to those items. To prevent any unauthorized access to that functions and variables it is used the reserved word static in front of the declaration of those items. This is a modifier and in fact it modifies the scope of the variables and functions it is used with. Those items (the one "marked" by static) are available only in the .c file they are declared in and that makes them private to that module.

It is important that the static variables are private because the behavior of the library relies on the fact that those variables are only modified in the way the library does. If someone else would change them without following those rules this would probably produce a mess, preventing our library to work properly.

These variables keep track of some important aspect of our library: the array menu_char is an array of char that keeps track of the letter the user must use to select an item of our menu, the array of strings menu_string instead takes care of storing the menu voices (i.e. of the descriptions of each menu item choice), finally the array of pointers to functions (please note the declaration) menu_functions is the array of our callbacks, each one associated with the correspondent menu key and menu description. Those arrays need to be populated "in parallel" for each menu item a key, a description and a function has to be provided (so it is important that no one else apart the library itself has access to those variables).

The string menu_caption is the menu title and the integer menu_pos is the variable used to keep track of what position inside the arrays has to be used when the a menu item is added.

The function menu_init performs the proper initialization of all those variables while the menu_clean_up is responsible to free all the dynamically allocated variables the library set up to properly working.

Note how the menu_set_caption checks if the caption has already been set, if yes the old caption is deleted and a new one is allocated of the proper dimension and correctly set. There are some "tricks" in the calculation of the caption size (a plus 1 is used): that is done to ensure that our string are always null terminated (see the following memset and memcpy).

The menu_add_item function add an item to our menu and so it wants a key, a description and a function to properly set up the callback associated to that choice: only a function which takes no argument and returns nothing is available, that is the simplest possibility, but of course different choices could be made.

The menu_function is the one we have to call when we want to show and use the menu, it automatically prints the menu and handles our choice by calling the associated callback. The function exits only when the command ‘x‘ is used (and so it is not available for any other menu command).

To get the user choice a private function menu_get_item is used: this function uses the getchar standard library function that return just one character form the standard input (which is the keyboard). The menu_get_item function continues to read one character until a "end of line" is found, then it considers the character immediately before the end of line as the entered command. This is due to the fact that the keys entered by the user are made available to the getchar only when the key return is hit (and that correspond to the "end of line"). This kind of management prevent the fact that multiple choice are entered at the same time: it is a simple approach, nevertheless it reminds us an important concept, every time a user input has to be processed some check has to be performed before to use that value.

Compiling the menu library

Suppose that our library is contained in the files menulib.c and menulib.h to compile the library we can use the following commands:

gcc -c menulib.c -o menulib.o
ar rcs libmenu.a menulib.o

The first command compiles the source file and produce an object file (the .o one): this is a binary intermediate form that needs further steps to be fully used. So that the second command (that uses the program ar which stands for archive) is used to produce the actual library (the .a file) using the menulib.o file (you can archive as many .o files you want into the library, just by listing all them).

The ar has several options that can be used, in this case they are contained in the rcs string which stands for:

  • s - write an object file index into the archive
  • r - insert the files member into archive (in this case just one .o file)
  • c - create the archive

That produces a libmenu.a file that can be used in different applications without any change to the source code of the library: we will in fact just use the header file and the library file (and so we will forget the source file).

An application using a menu

This is a possible application that uses the menu library:

#include "menulib.h"

#define M_CAPTION "This is the Greetings menu of the application"

#define CAPT1 "To say hello"
#define CAPT2 "To say good morning"
#define CAPT3 "To say good afternoon"
#define CAPT4 "To say good night"
#define CAPT5 "To say goodbye"
#define CAPT6 "To say bye"
#define CAPT7 "To say good evening"

void print_hello(void) {
   printf("Hello World!\n");
}

void print_morning(void) {
   printf("The early bird catches the worm! Get up!\n");
}

void print_afternoon(void) {
   printf("Good afternoon!\n");
}

void print_night(void) {
   printf("Sweet dreams, my love.\n");
}

void print_evening(void) {
   printf("Goog evening. I hope you are fine.\n");
}

void print_bye(void) {
   printf("I gotta go! Bye\n");
}

void print_goodbye(void) {
   printf("Goodbye Cruel World\n");
}

int main () {

   menu_init();

   menu_set_caption(M_CAPTION, strlen(M_CAPTION));

   menu_add_item('1', CAPT1, strlen(CAPT1), print_hello);
   menu_add_item('2', CAPT2, strlen(CAPT2), print_morning);
   menu_add_item('3', CAPT3, strlen(CAPT3), print_afternoon);
   menu_add_item('4', CAPT4, strlen(CAPT4), print_night);
   menu_add_item('5', CAPT5, strlen(CAPT5), print_goodbye);
   menu_add_item('6', CAPT6, strlen(CAPT6), print_bye);
   menu_add_item('7', CAPT7, strlen(CAPT7), print_evening);

   menu_function();

   menu_clean_up();

   return(0);
}

This example just uses the functions provided by the library, but it sets up its own callback functions to customize the behavior of the menu. We obtained a generic piece of code (the menu) that can be used in different applications using different callbacks (or pointer to functions).

I will let the details of this example to you, however just one thing is still missing: how we can obtain the full application using the library we just created. To do that we need the following commands:

gcc -c main.c -o main.o
gcc -o menu.exe main.o libmenu.a

First we need to compile our application file (we suppose that file is main.c) into an object file (main.o) then we link our application object file against our library using always gcc: this second command will produce an executable main.exe using the object file main.o which will be linked to the functions contained into the libmenu.a library.

To share this page click on the buttons below;