Reputation: 459
What is the need for function pointers? The standard answer for this seems to be callbacks, but why can't we just pass a function?
The book I was reading on C++ demonstrates passing a function as a parameter, and acknowledges that in actual fact the compiled turns this into a function pointer and passes that instead, because functions are not actual objects. It showed the equivalent code using function pointers, which was slightly more complex - if the code is equivalent, why bother to use a function pointer.
I presume there is a case when is simply isn't possible to pass the function, and one must pass a pointer instead? Can someone give me an example of this case, as it would help me understand why function pointers are useful.
Consider the following code:
#include <iostream>
using namespace std;
int add(int x) {
return ++x; //this is a copy, so it doesn't touch x
}
void runprint(int function(int x), int x) {
cout << function(x) << endl;
}
int main() {
runprint(add, 1);
return 0;
}
We are passing a function as a parameter, not a pointer. The function accepting the function (!), is not accepting a pointer.
Upvotes: 3
Views: 1112
Reputation: 1
Function pointer is a pointer that holds the address of the function. Function pointer is to invoke the function even if the name of the function is unknown. This is practical in using different function at runtime.
Upvotes: 0
Reputation: 28241
"Function" and "pointer to function" is the same.
There is the concept of a pointer, and the syntax of its usage; it's not clear what you are asking about.
A pointer to a function may be different from the function itself (the difference is not useful in c++ - see below) in that a function may occupy much space - its code can be arbitrarily complex. Manipulating (e.g. copying or searching/modifying) the code of a function is rarely useful, so c/c++ don't support it at all. If you want to modify the code of a function, cast a pointer to char*
, applying all the necessary precautions (I have never done it).
So if you are writing C, all you need is pointers to functions.
However...
If you have a pointer p
to a function, how do you want to call the function?
(*p)(18); // call the function with parameter 18
p(18); // the same, but looks better!
There is the slightly cleaner syntax not involving the *
sign. To support it, the authors of c/c++ invented the concept of "decay" - when your code mentions "a function", the compiler silently "corrects" it to mean "a pointer to a function" instead (in almost all circumstances; excuse me for not detailing further). This is very similar to the "decay" of an array to a pointer mentioned by vsoftco.
So in your example
void runprint(int function(int x), int x) {
cout << function(x) << endl;
}
the "function" type is actually a "pointer to function" type. Indeed, if you try to "overload":
void runprint(int (*function)(int x), int x) {
cout << function(x) << endl;
}
the compiler will complain about two identical functions with identical set of parameters.
Also, when making a variable of a function / pointer-to-function type
runprint(add, 1);
it also doesn't matter:
runprint(&add, 1); // does exactly the same
P.S. When declaring a function that receives a callback, I have mostly seen (and used) the explicitly written pointer. It has only now occurred to me that it's inconsistent to rely on function-to-pointer decay when calling the callback, but not when declaring my code. So if the question is
why does everyone declare callbacks using a pointer-to-function syntax, when a function syntax would be sufficient?
I'd answer "a matter of habit".
Upvotes: 3
Reputation: 16016
function
is considered a function pointer by g++:
$ cat fp.cpp
#include <typeinfo>
#include <iostream>
using namespace std;
int add(int x) {
return ++x; //this is a copy, so it doesn't touch x
}
void runprint(int function(int x), int x) {
cout << typeid(function).name() << endl;
int (*f)(int); // function pointer compatible with function argument
f = function;
cout << typeid(f).name() << endl;
cout << function(x) << endl;
}
int main() {
runprint(add, 1);
return 0;
}
$ g++ -Wall -std=c++11 -o fp fp.cpp
$ ./fp
PFiiE
PFiiE
2
Upvotes: 3