Function Pointer in C
-
Use
void (*func)()
Notation to Define Function Pointer in C - Use Function Pointer Array to Implement Type-Generic Programming Feature
This article will introduce how to use a function pointer in C.
Use void (*func)()
Notation to Define Function Pointer in C
Function pointers are yet another construct in C programming that implement advanced features like dynamic function calling, structures that include their own methods similar to object-oriented design, type-generic programming and etc.
Note that function pointer declaration can have complicated syntax, namely, void (*func)(void)
notation declares the pointer to void
function that takes no parameters. Although we assign the address of printInt
function, that takes a single int
argument to the void (*func)(void)
type function pointer in the following example.
Once the function pointer named func
is defined, it can be called with the usual function call notation func(arg)
or with dereferencing operator (*func)(arg)
.
#include <stdio.h>
#include <stdlib.h>
void printInt(int x) { printf("printed from printInt: %d\n", x); }
int main() {
int input1 = 10233;
void (*func)(int) = printInt;
func(input1);
(*func)(input1);
exit(EXIT_SUCCESS);
}
Output:
printed from printInt: 10233
printed from printDouble: 11.234000
Alternatively, we can define a new type alias of a function pointer using typedef
to make code more readable. Note that different function types would need separate typedef
statements.
In the following code sample, we define a pointer to a void function without any arguments; nonetheless, both printInt
and printDouble
function addresses are stored in the variable of type FuncPtr
.
It should be noted out that the address of the specific function can be taken with explicit &
operator or with the implicit assignment of function name itself, as demonstrated in the next example.
#include <stdio.h>
#include <stdlib.h>
typedef void (*FuncPtr)();
void printInt(int x) { printf("printed from printInt: %d\n", x); }
void printDouble(double x) { printf("printed from printDouble: %f\n", x); }
int main() {
int input1 = 10233;
double input2 = 11.234;
FuncPtr func1 = printInt;
FuncPtr func2 = printDouble;
func1(input1);
func2(input2);
exit(EXIT_SUCCESS);
}
Output:
printed from printInt: 10233
printed from printDouble: 11.234000
Use Function Pointer Array to Implement Type-Generic Programming Feature
Like other objects, one can define an array of function pointers with brackets []
notation. This array can be utilized to choose and call specific functions during run-time easily.
Notice that we are using the keyword _Generic
, which is switch
like an expression that lets the user choose the specific case base on the type evaluation of the controlling expression.
Consequently, we implement the following code example, where the corresponding print
function is called based on the type of the variable passed in the switch
condition. Note that, enum
type is also utilized to define constant values for different cases.
#include <stdio.h>
#include <stdlib.h>
enum TYPE { INTEGER, DOUBLE, INVALID };
#define typename(x) \
_Generic((x), int: INTEGER, double: DOUBLE, default: INVALID)
typedef void (*FuncPtr)();
void printInt(int x) { printf("printed from printInt: %d\n", x); }
void printDouble(double x) { printf("printed from printDouble: %f\n", x); }
int main() {
int input1 = 10233;
double input2 = 11.234;
FuncPtr func_ptrs[] = {printInt, printDouble};
switch (typename(input1)) {
case INTEGER:
func_ptrs[INTEGER](input1);
break;
case DOUBLE:
func_ptrs[DOUBLE](input1);
break;
case INVALID:
printf("No corresponding type found!\n");
default:
break;
}
switch (typename(input2)) {
case INTEGER:
func_ptrs[INTEGER](input2);
break;
case DOUBLE:
func_ptrs[DOUBLE](input2);
break;
case INVALID:
printf("No corresponding type found!\n");
default:
break;
}
exit(EXIT_SUCCESS);
}
Output:
printed from printInt: 10233
printed from printDouble: 11.234000
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook