This post is intend to understand and get the command over function pointer, starting from beginners to expert level in simple and step by step fashion. Post is very detailed because I am attempting to create a mental model to help beginners understand the syntax and basics of function pointers. If you are ok with detail happy reading.
Function pointers are an interesting and powerful tool but their syntax can be a little confusing. This post will going into C function pointers from the basics to simple usage to some quirks about function names and addresses. In the end it will give you an easy way to think about function pointers so their usage is more clear. Start with Level 1 to 5, step by step.
Let’s start with a very simple function to print out the message hello world and see how we can create a function pointer from there. Here we have a function called sayHello along with its function prototype. This function returns nothing (void) and doesn’t take any parameters. We call the function from main and it prints out “hello world”. Pretty simple. Now lets convert main to use a function pointer instead of calling the function directly. The syntax void (*sayHelloPtr)() on line 2 may look a little weird so let’s step by step it. On line 2 above we are assigning the sayHello function name to our newly created function pointer like this void (*sayHelloPtr)() = sayHello. We will go into more detail about function names later, but for now understand that a function name (label) is the address of the function and it can be assigned to a function pointer. This is similar to int *x = &myint where we assign the address of myint to an int pointer. Only in the case of a function, the address-of the function is the function name and we dont’ need the address-of operator. Simply put, the function name is the address-of the function. On line 3 we dereference and call our function pointer like this (*sayHelloPtr)(). Now that we have show the weird syntax understand that often function pointers are just treated and called as regular functions after being assigned. To modify our previous example. As before we assign the sayHello function to our function pointer, but now we call the function pointer just like we would call a regular function. We will get into function names later which will show why this works but for now understand that calling a function pointer with full syntax (*sayHelloPtr)() is the same as calling the function pointer as a regular function sayHelloPtr(). Now lets create a function pointer that still doesn’t return anything (void) but now has parameters. As before we have our function prototype, our function implementation and the executing of the fuction from main using a function pointer. The signature of both the prototype and its implementation have changed. Where before our sayHello function didn’t have parameters, the subtractAndPrint function takes two parameters, both integers, subtracts one from the other and prints the result. Let’s change our subtractAndPrint function to be called subtract and to return the result instead of printing it. Similar to the subtractAndPrint function except now the subtract function returns an int. The prototype and function signatures have changed as would be expected. Not much difference from before, we just added the int return value. Let’s move on to a little more complex example where we pass a function pointer into another function as a parameter. We have stepped through the main parts of the declaring and executing function pointers with and without parameters and return values. Now lets look at using a function pointer to execute different functions based on input. Let’s break this down. The main function calls domath twice, once for add and once for subtract, printing out the results. Let’s wrap up by talking a bit about function names and addresses as promised. A function name (label) is converted to a pointer to itself. This means that function names can be used where function pointers are required as input. It also leads to some very funky looking code that actually works. Take a look at some examples. Run this code and every function pointer will execute. Yes you will get some warnings about char conversion, this is a simple example. But the function pointers still work. This code isn’t an example of best practice. The takeaway is this. One, function names are converted to function pointers implicitly the same way that array names are converted to pointers implicitly when passed into functions. Function names can be used wherever a function pointer is required. Two, the address-of (&) and value-at-address (*) operators are almost always redundant when used against function names. I hope this helps clarify some things about function pointers and their usage. When understood, function pointers become a powerful tool in the C toolbox. In future posts I may go into more detailed usage of function pointers for things like callbacks and basic OOP in C. There are many use of function pointer but all they are summing around callback construct, so here i write two use cases for function pointers upon callback construction: => Implement Callback functions – used for Event Handlers, parser specialization, comparator function passing. => Dynamically function calling(One kind of callback use case) – Create plugins and extension, Enable-Disables some features upon certain events, creating Finite State Machines(FSM), etc For more Reading :- What are practical uses of function pointers in c ?A Simple Function and Function Pointer
#include <stdio.h>;
// function prototype
void sayHello();
// function implementation
void sayHello() {
printf("hello world");
}
// calling from main
int main() {
sayHello();
}
int main() {
void (*sayHelloPtr)() = sayHello;
(*sayHelloPtr)();
}
int main() {
void (*sayHelloPtr)() = sayHello;
sayHelloPtr();
}
A Function Pointer with Parameters
#include <stdio.h>
// function prototype
void subtractAndPrint(int x, int y);
// function implementation
void subtractAndPrint(int x, int y) {
int z = x - y;
printf("Simon says, the answer is: %d\n", z);
}
// calling from main
int main() {
void (*sapPtr)(int, int) = subtractAndPrint;
(*sapPtr)(10, 2);
sapPtr(10, 2);
}
A Function Pointer with Parameters and Return Value
#include <stdio.h>
// function prototype
int subtract(int x, int y);
// function implementation
int subtract(int x, int y) {
return x - y;
}
// calling from main
int main() {
int (*subtractPtr)(int, int) = subtract;
int y = (*subtractPtr)(10, 2);
printf("Subtract gives: %d\n", y);
int z = subtractPtr(10, 2);
printf("Subtract gives: %d\n", z);
}
Passing a Function Pointer as a Parameter
#include <stdio.h>
// function prototypes
int add(int x, int y);
int subtract(int x, int y);
int domath(int (*mathop)(int, int), int x, int y);
// add x + y
int add(int x, int y) {
return x + y;
}
// subtract x - y
int subtract(int x, int y) {
return x - y;
}
// run the function pointer with inputs
int domath(int (*mathop)(int, int), int x, int y) {
return (*mathop)(x, y);
}
// calling from main
int main() {
// call math function with add
int a = domath(add, 10, 2);
printf("Add gives: %d\n", a);
// call math function with subtract
int b = domath(subtract, 10, 2);
printf("Subtract gives: %d\n", b);
}
Function Names and Addresses
#include <stdio.h>
// function prototypes
void add(char *name, int x, int y);
// add x + y
void add(char *name, int x, int y) {
printf("%s gives: %d\n", name, x + y);
}
// calling from main
int main() {
// some funky function pointer assignment
void (*add1Ptr)(char*, int, int) = add;
void (*add2Ptr)(char*, int, int) = *add;
void (*add3Ptr)(char*, int, int) = &add;
void (*add4Ptr)(char*, int, int) = **add;
void (*add5Ptr)(char*, int, int) = ***add;
// execution still works
(*add1Ptr)("add1Ptr", 10, 2);
(*add2Ptr)("add2Ptr", 10, 2);
(*add3Ptr)("add3Ptr", 10, 2);
(*add4Ptr)("add4Ptr", 10, 2);
(*add5Ptr)("add5Ptr", 10, 2);
// this works too
add1Ptr("add1PtrFunc", 10, 2);
add2Ptr("add2PtrFunc", 10, 2);
add3Ptr("add3PtrFunc", 10, 2);
add4Ptr("add4PtrFunc", 10, 2);
add5Ptr("add5PtrFunc", 10, 2);
}
Conclusion
What are practical uses of function pointers in c ?
Suggested Reading
- What are practical uses of function pointers in c ?
- How can I write a function that takes a variable number of arguments?
- Interesting Facts about Macros and Preprocessors
- structure padding and packing in c example
If you like this Article, then don’t forget to Click on Social likes buttons.