Reputation: 2686
I have just read an interesting question here that makes me wonder about two more things:
void *
or does it hold richer information (like return type, number of arguments and arguments types?)Upvotes: 32
Views: 6233
Reputation: 9203
Why would someone compare pointers? Consider the following scenario -
You have an array of function pointers, say it is a call back chain and you need to call each one of them. The list is terminated with a NULL
(or sentinel) function pointer. You need to compare if you have reached the end of the list by comparing with this sentinel pointer. Also, this case justifies previous OPs concern that different functions should have different pointers even if they are similar.
Does the compiler see them differently? Yes. The type information includes all the information about the arguments and the return type.
For example, the following code will/should be rejected by the compiler -
void foo(int a);
void (*bar)(long) = foo; // Without an explicit cast
Upvotes: 19
Reputation: 148880
The classical part about function pointers is already discussed in other's answer:
void *
and even in C language).But C has a (legacy) function declaration mode. In addition to the full prototype mode that declares the return type and the type for all parameters, C can use the so called parameter list mode which is the old K&R mode. In this mode, the declaration only declares the return type:
int (*fptr)();
In C it declares a pointer to function returning an int
and accepting arbitrary parameters. Simply it will be undefined behaviour (UB) to use it with a wrong parameter list.
So this is legal C code:
#include <stdio.h>
#include <string.h>
int add2(int a, int b) {
return a + b;
}
int add3(int a, int b, int c) {
return a + b + c;
}
int(*fptr)();
int main() {
fptr = add2;
printf("%d\n", fptr(1, 2));
fptr = add3;
printf("%d\n", fptr(1, 2, 3));
/* fprintf("%d\n", fptr(1, 2)); Would be UB */
return 0;
}
Don't pretend I have advised you to do so! It is now considered as an obsolescent feature and should be avoided. I am just warning you against it. IMHO it could only have some exceptional acceptable use cases.
Upvotes: 5
Reputation: 206567
- Why should anyone compare function pointers, given that by conception, functions uniqueness is ensured by their different names?
A function pointer can point to different functions at different times in a program.
If you have a variable such as
void (*fptr)(int);
it can point to any function that accepts an int
as input and returns void
.
Let's say you have:
void function1(int)
{
}
void function2(int)
{
}
You can use:
fptr = function1;
foo(fptr);
or:
fptr = function2;
foo(fptr);
You might want to do different things in foo
depending on whether fptr
points to one function or another. Hence, the need for:
if ( fptr == function1 )
{
// Do stuff 1
}
else
{
// Do stuff 2
}
- Does the compiler see function pointers as special pointers? I mean does it see them like, let's say, pointers to void * or does it hold richer information (like return type, number of arguments and arguments types?)
Yes, function pointers are special pointers, different from pointers that point to objects.
The type of a function pointer has all that information at compile time. Hence, give a function pointer, the compiler will have all that information - the return type, the number of arguments and their types.
Upvotes: 18
Reputation: 213523
1) There are lots of situations. Take for example the typical implementation of a finite state machine:
typedef void state_func_t (void);
const state_func_t* STATE_MACHINE[] =
{
state_init,
state_something,
state_something_else
};
...
for(;;)
{
STATE_MACHINE[state]();
}
You might need to include some extra code in the caller for a specific situation:
if(STATE_MACHINE[state] == state_something)
{
print_debug_stuff();
}
2) Yes the C compiler sees them as distinct types. In fact function pointers have stricter type safety than other types of C, because they cannot get implicitly converted to/from void*
, like pointers to object types can. (C11 6.3.2.3/1). Nor can they be explicitly cast to/from void*
- doing so would invoke non-standard extensions.
Everything in the function pointer matters to determine its type: the type of the return value, the type of the parameters and the number of parameters. All of these must match, or two function pointers are not compatible.
Upvotes: 2
Reputation: 3204
Function pointers are variables. Why should anyone compare variables, given that by concept, variables uniqueness is ensured by their different names? Well, sometimes two variables can have the same value and you want to find out whether it's the case.
C considers pointers to functions with the same argument list and return value to be of the same type.
Upvotes: 1
Reputation: 170055
Why should anyone compare function pointers? Here's one example:
#include <stdbool.h>
/*
* Register a function to be executed on event. A function may only be registered once.
* Input:
* arg - function pointer
* Returns:
* true on successful registration, false if the function is already registered.
*/
bool register_function_for_event(void (*arg)(void));
/*
* Un-register a function previously registered for execution on event.
* Input:
* arg - function pointer
* Returns:
* true on successful un-registration, false if the function was not registered.
*/
bool unregister_function_for_event(void (*arg)(void));
The body of register_function_for_event
only sees arg
. It doesn't see any function name. It must compare function pointers to report someone is registering the same function twice.
And if you want to support something like unregister_function_for_event
to complement the above, the only information you have is the function address. So you again would need to pass it in, and compare against it, to allow removal.
As for the richer information, yes. When the function type contains a prototype, it's part of the static type information. Mind you that in C a function pointer can be declared without a prototype, but that is an obsolescent feature.
Upvotes: 36
Reputation: 210402
Imagine how you would implement functionality similar to that of WNDCLASS
?
It has a lpszClassName
to distinguish window classes from each other, but let's say you didn't need (or didn't have) a string available to distinguish different classes from each other.
What you do have is the window class procedure lpfnWndProc
(of type WindowProc
).
So now what would you do if someone calls RegisterClass
twice with the same lpfnWndProc
?
You need to detect re-registrations of the same class somehow and return an error.
That's one case when the logical thing to do is to compare the callback functions.
Upvotes: 2