Scripting

Function Pointers in C Language

The method to invoke the functions in the C language is to call the function by sending the data that we want to process in it in its input arguments and then obtain the result in its output argument. Because of its simplicity, this method is part of the C programming that programmers usually use, since it fulfills all the requirements needed to create an application. However, the C language offers the possibility to invoke the functions by their pointer. This method is a very powerful tool that, in the hands of a creative programmer, can give the same program with different execution dynamics in real time with only a few lines of code.

In this Linux Ways article, you will learn what a function pointer is. We’ll explain how to declare it and assign it with the memory address where a function is located. We will also see how to call a function with its pointer and how to pass the arguments in it. Then, we will see some practical examples with code and images that show how to implement the simple function pointers and arrays.

Function Pointer in the C language

A function pointer points to the starting address where a function is located in the memory. Unlike a pointer to a conventional variable in C, pointers to functions act on the counter that controls the addressing of program memory, producing a jump to that address, and executing the code.

Although these types of pointers can be used to invoke a function, replacing the traditional C call, their true potential lies in the implementation of vectorized arrays of function pointers or in callbacks.

How to Declare a Pointer to a Function in the C Language

To declare a pointer of this type, we first need to know the prototype of the function to which we want to assign the pointer and the type of data that it manages in its arguments. Next, let’s look at the syntax to declare a pointer to a function:

output type (*identifier of pointer)(input type);

As we can see, we must first specify the data type of the function’s output argument, followed by the identifier that we want to assign to the pointer, preceded by the “*” operator and enclosed in parentheses. Finally, also enclosed in parentheses, the data type of the function’s input arguments which, if more than one, must be separated by commas.

Next, we will see the declaration of the “Ptr_func” pointer to a function whose input argument is of type int and the output is of type void:

void (*Ptr_func)(int);

How to Assign the Memory Address of a Function with a Pointer in the C Language

We have already seen how to declare a pointer to a function. Now, we will see how to associate this pointer with the memory address where the function is located. Assigning an address to a pointer is done by an assignment operation as shown in the following syntax:

pointer identifier = & function identifier;

As we can see in the syntax, the identifier of the previously declared pointer is to the left of the assignment operator, while the identifier of the function to the right, preceded by the “&” symbol. The following fragment shows how to assign the memory address of the “myfunction” function:

Ptr_f = & myfunction;

How to Invoke a Function through Its Pointer in the C Language

So far, we have seen how to declare a function pointer and assign it with the memory address. Now, we will see how to use this function by accessing it through its pointer.

To invoke a function by its pointer, we must enclose the pointer, preceded by the “*” character on one side and the argument variables on the other side, separately in parentheses. The following fragment shows how to use the “myfunction” function pointed to by the “Ptr_func” pointer with the variable “a” as the input argument.

(*Ptr_func) (a);

In this example, we will create a very simple application consisting of two functions, the main() function and the myfunction() function.

The myfunction() function shows the string that is sent as an input argument, while the main() function declares the “Ptr_func” function pointer, assigns it the address of myfunction(), and then calls the function using its pointer, passing the “str” string as an argument. In the following, we will see the code for this example:

#include <stdio.h>

void myfunction (char *str);

void main ()
{
char *str ="\nI am the input argument";
void (* Ptr_func) (char*)= &myfunction;
(*Ptr_func) (str);
}

void myfunction (char *str)
{
 printf("I am myfunction%s\n", str);
}

The image that we see in the following shows the execution of this code:

 

Arrays of Pointers to Functions in the C Language

Now, we’ll see how we can get more potential out of function pointers by creating a program with multiple working dynamics and with very little code.

The functions that we will use in this example are “func_1”, “func_2”, “func_3”, and “func_4”. Each of them displays a message indicating in which code fragment is in the program. In the following, we will see the code of the described functions which we copy and save in a file called “functions.c” in the same directory where our main() file is located:

void func_1 (void);
void func_2 (void);
void func_3 (void);
void func_4 (void);

void func_1 (void)
{
 printf("Code snippet 1\n");
}
void func_2 (void)
{
 printf("Code snippet 2\n");
}
void func_3 (void)
{
 printf("Code snippet 3\n");
}
void func_4 (void)
{
 printf("Code snippet 4\n");
}

Now, we create a main() function with a vector for the command line arguments. In it, we declare an array of Ptr_f[] function pointers with five elements and assign the address of the functions to each element from the “functions.c” file.

The program contains a “for” loop in which the escape condition is determined by the number of command line arguments received that are specified in the “argc” integer. This loop fetches the received command line arguments, converts them to integers, and the obtained values index the Ptr_f[] pointer array.

In each cycle of the loop, a function is called with a pointer to the “Ptr_f” array which is indexed by the integer that is received in the command line arguments. In this way, we obtain a program that executes a sequence of function calls consisting of different code fragments, each belonging to a function. We will see the code for the main() function for this example:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "functions.c"

void main ( int argc, char * argv[])
{
void (* Ptr_f[5] )(void)={*Ptr_f ,&func_1, &func_2, &func_3, &func_4};
char arg;
for (int i = 1; i!= argc; i++)
   {
   (*Ptr_f[atoi(argv[i])])();
   }

}

Now, we compile this code and create an executable file (.bin) with it as shown in the following:

Now, let’s run this program with the call sequence of 1, 2, 3, 4 as shown in the following:

As we can see in the picture, the program has executed the calling sequence of 1, 2, 3 and 4. Now, let’s look at a more complex calling sequence:

As we can see, the program can execute various assembled code sequences in real time. Although this example is a simple program so the readers can better understand the concept, this method can provide powerful processing resources.

Conclusion

In this Linux Ways article, we just explained what function pointers in the C language are all about, how to declare them, how to assign the address of the function, and how to call it using its pointer.

We then implemented the function pointers in practical examples with code snippets and images that show the simplest ways to use a function pointer. In another section, we showed you how to implement the vectorized function pointers, seeing the full potential of this powerful resource of C.

Similar Posts