Function pointer
A function pointer, also called a subroutine pointer or procedure pointer, is a pointer that points to a function. As opposed to referencing a data value, a function pointer points to executable code within memory. Dereferencing the function pointer yields the referenced function, which can be invoked and passed arguments just as in a normal function call. Such an invocation is also known as an "indirect" call, because the function is being invoked indirectly through a variable instead of directly through a fixed identifier or address.
Function pointers can be used to simplify code by providing a simple way to select a function to execute based on run-time values.
Function pointers are supported by third-generation programming languages and object-oriented programming languages.
Simple function pointers
The simplest implementation of a function pointer is as a variable containing the address of the function within executable memory. Older third-generation languages such as PL/I and COBOL, as well as more modern languages such as Pascal and C generally implement function pointers in this manner.Example in C
The following C program illustrates the use of two function pointers:- func1 takes one double-precision parameter and returns another double, and is assigned to a function which converts centimetres to inches.
- func2 takes a pointer to a constant character array as well as an integer and returns a pointer to a character, and is assigned to a C string handling function which returns a pointer to the first occurrence of a given character in a character array.
- include
/* for printf */ - include
/* for strchr */
// "strchr" is part of the C string handling
// See https://en.wikipedia.org/wiki/C_string_handling#Functions
int main
The next program uses a function pointer to invoke one of two functions indirectly from another function. The program operates by having function
main
call function compute_sum
twice, passing it a pointer to the library function sin
the first time, and a pointer to function cos
the second time. Function compute_sum
in turn invokes one of the two functions indirectly by dereferencing its function pointer argument funcp
multiple times, adding together the values that the invoked function returns and returning the resulting sum. The two sums are written to the standard output by main
.- include
- include
double compute_sum
double square
int main
Functors
Functors, or function objects, are similar to function pointers, and can be used in similar ways. A functor is an object of a class type that implements the function-call operator, allowing the object to be used within expressions using the same syntax as a function call. Functors are more powerful than simple function pointers, being able to contain their own data values, and allowing the programmer to emulate closures. They are also used as callback functions if it is necessary to use a member function as a callback function.Many "pure" object-oriented languages do not support function pointers. Something similar can be implemented in these kinds of languages, though, using references to interfaces that define a single method. CLI languages such as C# and Visual Basic.NET implement type-safe function pointers with delegates.
In other languages that support first-class functions, functions are regarded as data, and can be passed, returned, and created dynamically directly by other functions, eliminating the need for function pointers.
Extensively using function pointers to call functions may produce a slow-down for the code on modern processors, because branch predictor may not be able to figure out where to branch to although this effect can be overstated as it is often amply compensated for by significantly reduced non-indexed table lookups.
Method pointers
C++ includes support for object-oriented programming, so classes can have methods. Non-static member functions have an implicit parameter which is the pointer to the object it is operating on, so the type of the object must be included as part of the type of the function pointer. The method is then used on an object of that class by using one of the "pointer-to-member" operators:.*
or ->*
.Although function pointers in C and C++ can be implemented as simple addresses, so that typically
sizeofsizeof
, member pointers in C++ are sometimes implemented as "fat pointers", typically two or three times the size of a simple function pointer, in order to deal with virtual methods and virtual inheritance.In C++
In C++, in addition to the method used in C, it is also possible to use the C++ standard library class template, of which the instances are function objects:- include
- include
static double f
int main
Pointers to member functions in C++
This is how C++ uses function pointers when dealing with member functions of classes or structs. These are invoked using an object pointer or a this call. They are type safe in that you can only call members of that class using a pointer of that type. This example also demonstrates the use of a typedef for the pointer to member function added for simplicity. Function pointers to static member functions are done in the traditional 'C' style because there is no object pointer for this call required.- include
class Foo ;
int bar1)
typedef int;
int bar2
typedef int;
int bar3
int main
Alternate C and C++ Syntax
The C and C++ syntax given above is the canonical one used in all the textbooks - but it's difficult to read and explain. Even the abovetypedef
examples use this syntax. However, every C and C++ compiler supports a more clear and concise mechanism to declare function pointers: use typedef
, but don't store the pointer as part of the definition. Note that the only way this kind of typedef
can actually be used is with a pointer - but that highlights the pointer-ness of it.C and C++
// This declares 'F', a function that accepts a 'char' and returns an 'int'. Definition is elsewhere.
int F;
// This defines 'Fn', a type of function that accepts a 'char' and returns an 'int'.
typedef int Fn;
// This defines 'fn', a variable of type pointer-to-'Fn', and assigns the address of 'F' to it.
Fn *fn = &F; // Note '&' not required - but it highlights what is being done.
// This calls 'F' using 'fn', assigning the result to the variable 'a'
int a = fn;
// This defines 'Call', a function that accepts a pointer-to-'Fn', calls it, and returns the result
int Call // Call
// This calls function 'Call', passing in 'F' and assigning the result to 'call'
int call = Call; // Again, '&' is not required
// LEGACY: Note that to maintain existing code bases, the above definition style can still be used first;
// then the original type can be defined in terms of it using the new style.
// This defines 'PFn', a type of pointer-to-type-Fn.
typedef Fn *PFn;
// 'PFn' can be used wherever 'Fn *' can
PFn pfn = F;
int CallP;
C++
These examples use the above definitions. In particular, note that the above definition forFn
can be used in pointer-to-member-function definitions:// This defines 'C', a class with similar static and member functions,
// and then creates an instance called 'c'
class C c; // C
// This defines 'p', a pointer to 'C' and assigns the address of 'c' to it
C *p = &c;
// This assigns a pointer-to-'Static' to 'fn'.
// Since there is no 'this', 'Fn' is the correct type; and 'fn' can be used as above.
fn = &C::Static;
// This defines 'm', a pointer-to-member-of-'C' with type 'Fn',
// and assigns the address of 'C::Member' to it.
// You can read it right-to-left like all pointers:
// "'m' is a pointer to member of class 'C' of type 'Fn'"
Fn C::*m = &C::Member;
// This uses 'm' to call 'Member' in 'c', assigning the result to 'cA'
int cA = ;
// This uses 'm' to call 'Member' in 'p', assigning the result to 'pA'
int pA = ;
// This defines 'Ref', a function that accepts a reference-to-'C',
// a pointer-to-member-of-'C' of type 'Fn', and a 'char',
// calls the function and returns the result
int Ref // Ref
// This defines 'Ptr', a function that accepts a pointer-to-'C',
// a pointer-to-member-of-'C' of type 'Fn', and a 'char',
// calls the function and returns the result
int Ptr // Ptr
// LEGACY: Note that to maintain existing code bases, the above definition style can still be used first;
// then the original type can be defined in terms of it using the new style.
// This defines 'FnC', a type of pointer-to-member-of-class-'C' of type 'Fn'
typedef Fn C::*FnC;
// 'FnC' can be used wherever 'Fn C::*' can
FnC fnC = &C::Member;
int RefP;