I had some experience lately with function pointers in C.
So going on with the tradition of answering your own questions, I decided to make a small summary of the very basics, for those who need a quick dive-in to the subject.
I had some experience lately with function pointers in C.
So going on with the tradition of answering your own questions, I decided to make a small summary of the very basics, for those who need a quick dive-in to the subject.
function pointers are useful in many situations, eg:
This->lpVtbl->AddRef(This);
AddRef is a pointer to a function.One of my favorite uses for function pointers is as cheap and easy iterators -
Function pointers in C
Let's start with a basic function which we will be pointing to:
First thing, let's define a pointer to a function which receives 2
int
s and returns anint
:Now we can safely point to our function:
Now that we have a pointer to the function, let's use it:
Passing the pointer to another function is basically the same:
We can use function pointers in return values as well (try to keep up, it gets messy):
But it's much nicer to use a
typedef
:Starting from scratch function has Some Memory Address From Where They start executing. In Assembly Language They Are called as (call "function's memory address").Now come back to C If function has a memory address then they can be manipulated by Pointers in C.So By the rules of C
1.First you need to declare a pointer to function 2.Pass the Address of the Desired function
****Note->the functions should be of same type****
This Simple Programme will Illustrate Every Thing.
After That lets See How machine Understands Them.Glimpse of machine instruction of the above programme in 32 bit architecture.
The red mark area is showing how the address is being exchanged and storing in eax.Then their is a call instruction on eax. eax contains the desired address of the function
A function pointer is a variable that contains the address of a function. Since it is a pointer variable though with some restricted properties, you can use it pretty much like you would any other pointer variable in data structures.
The only exception I can think of is treating the function pointer as pointing to something other than a single value. Doing pointer arithmetic by incrementing or decrementing a function pointer or adding/subtracting an offset to a function pointer isn't really of any utility as a function pointer only points to a single thing, the entry point of a function.
The size of a function pointer variable, the number of bytes occupied by the variable, may vary depending on the underlying architecture, e.g. x32 or x64 or whatever.
The declaration for a function pointer variable needs to specify the same kind of information as a function declaration in order for the C compiler to do the kinds of checks that it normally does. If you don't specify a parameter list in the declaration/definition of the function pointer, the C compiler will not be able to check the use of parameters. There are cases when this lack of checking can be useful however just remember that a safety net has been removed.
Some examples:
The first two declararations are somewhat similar in that:
func
is a function that takes anint
and achar *
and returns anint
pFunc
is a function pointer to which is assigned the address of a function that takes anint
and achar *
and returns anint
So from the above we could have a source line in which the address of the function
func()
is assigned to the function pointer variablepFunc
as inpFunc = func;
.Notice the syntax used with a function pointer declaration/definition in which parenthesis are used to overcome the natural operator precedence rules.
Several Different Usage Examples
Some examples of usage of a function pointer:
You can use variable length parameter lists in the definition of a function pointer.
Or you can not specify a parameter list at all. This can be useful but it eliminates the opportunity for the C compiler to perform checks on the argument list provided.
C style Casts
You can use C style casts with function pointers. However be aware that a C compiler may be lax about checks or provide warnings rather than errors.
Compare Function Pointer to Equality
You can check that a function pointer is equal to a particular function address using an
if
statement though I am not sure how useful that would be. Other comparison operators would seem to have even less utility.An Array of Function Pointers
And if you want to have an array of function pointers each of the elements of which the argument list has differences then you can define a function pointer with the argument list unspecified (not
void
which means no arguments but just unspecified) something like the following though you may see warnings from the C compiler. This also works for a function pointer parameter to a function:C style
namespace
Using Globalstruct
with Function PointersYou can use the
static
keyword to specify a function whose name is file scope and then assign this to a global variable as a way of providing something similar to thenamespace
functionality of C++.In a header file define a struct that will be our namespace along with a global variable that uses it.
Then in the C source file:
This would then be used by specifying the complete name of global struct variable and member name to access the function. The
const
modifier is used on the global so that it can not be changed by accident.Application Areas of Function Pointers
A DLL library component could do something similar to the C style
namespace
approach in which a particular library interface is requested from a factory method in a library interface which supports the creation of astruct
containing function pointers.. This library interface loads the requested DLL version, creates a struct with the necessary function pointers, and then returns the struct to the requesting caller for use.and this could be used as in:
The same approach can be used to define an abstract hardware layer for code that uses a particular model of the underlying hardware. Function pointers are filled in with hardware specific functions by a factory to provide the hardware specific functionality that implements functions specified in the abstract hardware model. This can be used to provide an abstract hardware layer used by software which calls a factory function in order to get the specific hardware function interface then uses the function pointers provided to perform actions for the underlying hardware without needing to know implementation details about the specific target.
Function Pointers to create Delegates, Handlers, and Callbacks
You can use function pointers as a way to delegate some task or functionality. The classic example in C is the comparison delegate function pointer used with the Standard C library functions
qsort()
andbsearch()
to provide the collation order for sorting a list of items or performing a binary search over a sorted list of items. The comparison function delegate specifies the collation algorithm used in the sort or the binary search.Another use is similar to applying an algorithm to a C++ Standard Template Library container.
Another example is with GUI source code in which a handler for a particular event is registered by providing a function pointer which is actually called when the event happens. The Microsoft MFC framework with its message maps uses something similar to handle Windows messages that are delivered to a window or thread.
Asynchronous functions that require a callback are similar to an event handler. The user of the asynchronous function calls the asynchronous function to start some action and provides a function pointer which the asynchronous function will call once the action is complete. In this case the event is the asynchronous function completing its task.
Another good use for function pointers:
Switching between versions painlessly
They're very handy to use for when you want different functions at different times, or different phases of development. For instance, I'm developing an application on a host computer that has a console, but the final release of the software will be put on an Avnet ZedBoard (which has ports for displays and consoles, but they are not needed/wanted for the final release). So during development, I will use
printf
to view status and error messages, but when I'm done, I don't want anything printed. Here's what I've done:version.h
In
version.c
I will define the 2 function prototypes present inversion.h
version.c
Notice how the function pointer is prototyped in
version.h
asvoid (* zprintf)(const char *, ...);
When it is referenced in the application, it will start executing wherever it is pointing, which has yet to be defined.
In
version.c
, notice in theboard_init()
function wherezprintf
is assigned a unique function (whose function signature matches) depending on the version that is defined inversion.h
zprintf = &printf;
zprintf calls printf for debugging purposesor
zprintf = &noprint;
zprintf just returns and will not run unnecessary codeRunning the code will look like this:
mainProg.c
The above code will use
printf
if in debug mode, or do nothing if in release mode. This is much easier than going through the entire project and commenting out or deleting code. All that I need to do is change the version inversion.h
and the code will do the rest!