I wonder, when we create the function
int compar(const void *, const void *)
and we merely pass its name into one of the parameters of qsort and bsearch, how do those functions recognize said essentially random word (since we've never explicitly stated it is a function pointer, but rather an actual function) and use it as a parameter? Is there an explicit cast in the function declarations of qsort and bsearch or something?
This has nothing to do with the qsort and bsearch functions themselves, rather function names are implicitly converted by the compiler into function pointers as per the standard, C11 6.3.2.1 Language / Conversions / Other operands / Lvalues, arrays, and function designators:
A function designator is an expression that has function type. Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, a function designator with type "function returning type" is converted to an expression that has type "pointer to function returning type".
That means that, when you pass compar to qsort() (for example), it's the actual pointer to the function that gets passed, not some "essentially random word".
The reasons for implicitly treating a function identifier as its address lie long ago in the past but (and this whole section is supposition on my part, based on what I'd like to consider intelligent reasoning, but in no way definitive) it's likely to be because the value of a function makes no sense. With an identifier int i = 5;, it has a value (5), and you can also use &i to get it's address.
However, for functions, they don't really have values as such. You can call them to generate a value, xyzzy(), and you can get their address, &xyzzy, for later calling via a function pointer.
But they have no real intrinsic value separate from their address like the integer i does. So early compilers (pre-ANSI) simply allowed the shorthand xyzzy to mean &xyzzy. And, of course, since the original mandate of ANSI was to codify existing practice rather than create a new language, they preserved this behaviour.
If K&R had gone the other way and decided xyzzy should be a call to the function passing no parameters, the same as xyzzy(), the world would be a different place :-)
Related
Why and how does dereferencing a function pointer just "do nothing"?
This is what I am talking about:
#include<stdio.h>
void hello() { printf("hello"); }
int main(void) {
(*****hello)();
}
From a comment over here:
function pointers dereference just
fine, but the resulting function
designator will be immediately
converted back to a function pointer
And from an answer here:
Dereferencing (in way you think) a
function's pointer means: accessing a
CODE memory as it would be a DATA
memory.
Function pointer isn't suppose to be
dereferenced in that way. Instead, it
is called.
I would use a name "dereference" side
by side with "call". It's OK.
Anyway: C is designed in such a way
that both function name identifier as
well as variable holding function's
pointer mean the same: address to CODE
memory. And it allows to jump to that
memory by using call () syntax either
on an identifier or variable.
How exactly does dereferencing of a function pointer work?
It's not quite the right question. For C, at least, the right question is
What happens to a function value in an rvalue context?
(An rvalue context is anywhere a name or other reference appears where it should be used as a value, rather than a location — basically anywhere except on the left-hand side of an assignment. The name itself comes from the right-hand side of an assignment.)
OK, so what happens to a function value in an rvalue context? It is immediately and implicitly converted to a pointer to the original function value. If you dereference that pointer with *, you get the same function value back again, which is immediately and implicitly converted into a pointer. And you can do this as many times as you like.
Two similar experiments you can try:
What happens if you dereference a function pointer in an lvalue context—the left-hand side of an assignment. (The answer will be about what you expect, if you keep in mind that functions are immutable.)
An array value is also converted to a pointer in an lvalue context, but it is converted to a pointer to the element type, not to a pointer to the array. Dereferencing it will therefore give you an element, not an array, and the madness you show doesn't occur.
Hope this helps.
P.S. As to why a function value is implicitly converted to a pointer, the answer is that for those of us who use function pointers, it's a great convenience not to have to use &'s everywhere. There's a dual convenience as well: a function pointer in call position is automatically converted to a function value, so you don't have to write * to call through a function pointer.
P.P.S. Unlike C functions, C++ functions can be overloaded, and I'm not qualified to comment on how the semantics works in C++.
C++03 §4.3/1:
An lvalue of function type T can be converted to an rvalue of type “pointer to T.” The result is a pointer to the function.
If you attempt an invalid operation on a function reference, such as the unary * operator, the first thing the language tries is a standard conversion. It's just like converting an int when adding it to a float. Using * on a function reference causes the language to take its pointer instead, which in your example, is square 1.
Another case where this applies is when assigning a function pointer.
void f() {
void (*recurse)() = f; // "f" is a reference; implicitly convert to ptr.
recurse(); // call operator is defined for pointers
}
Note that this doesn't work the other way.
void f() {
void (&recurse)() = &f; // "&f" is a pointer; ERROR can't convert to ref.
recurse(); // OK - call operator is *separately* defined for references
}
Function reference variables are nice because they (in theory, I've never tested) hint to the compiler that an indirect branch may be unnecessary, if initialized in an enclosing scope.
In C99, dereferencing a function pointer yields a function designator. §6.3.2.1/4:
A function designator is an expression that has function type. Except when it is the operand of the sizeof operator or the unary & operator, a function designator with type ‘‘function returning type’’ is converted to an expression that has type ‘‘pointer to function returning type’’.
This is more like Norman's answer, but notably C99 has no concept of rvalues.
It happens with a few implicit conversions. Indeed, per the C standard:
ISO/IEC 2011, section 6.3.2.1 Lvalues, arrays, and function designators, paragraph 4
A function designator is an expression that has function type. Except when it is the operand of the sizeof operator or the unary & operator, a function designator with type “function returning type” is converted to an expression that has type “pointer to function returning type”.
Consider the following code:
void func(void);
int main(void)
{
void (*ptr)(void) = func;
return 0;
}
Here, the function designator func has the type “function returning void” but is immediately converted to an expression that has type “pointer to function returning void”. However, if you write
void (*ptr)(void) = &func;
then the function designator func has the type “function returning void” but the unary & operator explicitly take the address of that function, eventually yielding the type “pointer to function returning void”.
This is mentioned in the C standard:
ISO/IEC 2011, section 6.5.3.2 Address and indirection operators, paragraph 3
The unary & operator yields the address of its operand. If the operand has type “type”, the result has type “pointer to type”.
In particular, dereferencing a function pointer is redundant. Per the C standard:
ISO/IEC 2011, section 6.5.2.2 Function calls, paragraph 1
The expression that denotes the called function shall have type “pointer to function returning void” or returning a complete object type other than an array type. Most often, this is the result of converting an identifier that is a function designator.
ISO/IEC 2011, section 6.5.3.2 Address and indirection operators, paragraph 4
The unary * operator denotes indirection. If the operand points to a function, the result is a function designator.
So when you write
ptr();
the function call is evaluated with no implicit conversion because ptr is already a pointer to function. If you explicitly dereference it with
(*ptr)();
then the dereferencing yields the type “function returning void” which is immediately converted back to the type “pointer to function returning void” and the function call occurs. When writing an expression composed of x unary * indirection operators such as
(****ptr)();
then you just repeat the implicit conversions x times.
It does make sense that calling functions involves function pointers. Before executing a function, a program pushes all of the parameters for the function onto the stack in the reverse order that they are documented. Then the program issues a call instruction indicating which function it wishes to start. The call instruction does two things:
First it pushes the address of the next instruction, which is the return address, onto the stack.
Then, it modifies the instruction pointer %eip to point to the start of the function.
Since calling a function does involve modifying an instruction pointer, which is a memory address, it makes sense that the compiler implicitly converts a function designator to a pointer to function.
Even though it may seems unrigorous to have these implicit conversions, it can be useful in C (unlike C++ which have namespaces)
to take advantage of the namespace defined by a struct identifier to encapsulate variables.
Consider the following code:
void create_person(void);
void update_person(void);
void delete_person(void);
struct Person {
void (*create)(void);
void (*update)(void);
void (*delete)(void);
};
static struct Person person = {
.create = &create_person,
.update = &update_person,
.delete = &delete_person,
};
int main(void)
{
person.create();
person.update();
person.delete();
return 0;
}
It is possible to hide the implementation of the library in other translation units and to choose to only expose the struct encapsulating the pointers to functions, to use them in place of the actual function designators.
Put yourself in the shoes of the compiler writer. A function pointer has a well defined meaning, it is a pointer to a blob of bytes that represent machine code.
What do you do when the programmer dereferences a function pointer? Do you take the first (or 8) bytes of the machine code and reinterpret that as a pointer? Odds are about 2 billion to one that this won't work. Do you declare UB? Plenty of that going around already. Or do you just ignore the attempt? You know the answer.
How exactly does dereferencing of a function pointer work?
Two steps. The first step is at compile time, the second at runtime.
In step one, the compiler sees it has a pointer and a context in which that pointer is dereferenced (such as (*pFoo)() ) so it generates code for that situation, code that will be used in step 2.
In step 2, at runtime the code is executed. The pointer contains some bytes indicating which function should be executed next. These bytes are somehow loaded into the CPU. A common case is a CPU with an explicit CALL [register] instruction. On such systems, a function pointer can be simply the address of a function in memory, and the derefencing code does nothing more than loading that address into a register followed by a CALL [register] instruction.
Why and how does dereferencing a function pointer just "do nothing"?
This is what I am talking about:
#include<stdio.h>
void hello() { printf("hello"); }
int main(void) {
(*****hello)();
}
From a comment over here:
function pointers dereference just
fine, but the resulting function
designator will be immediately
converted back to a function pointer
And from an answer here:
Dereferencing (in way you think) a
function's pointer means: accessing a
CODE memory as it would be a DATA
memory.
Function pointer isn't suppose to be
dereferenced in that way. Instead, it
is called.
I would use a name "dereference" side
by side with "call". It's OK.
Anyway: C is designed in such a way
that both function name identifier as
well as variable holding function's
pointer mean the same: address to CODE
memory. And it allows to jump to that
memory by using call () syntax either
on an identifier or variable.
How exactly does dereferencing of a function pointer work?
It's not quite the right question. For C, at least, the right question is
What happens to a function value in an rvalue context?
(An rvalue context is anywhere a name or other reference appears where it should be used as a value, rather than a location — basically anywhere except on the left-hand side of an assignment. The name itself comes from the right-hand side of an assignment.)
OK, so what happens to a function value in an rvalue context? It is immediately and implicitly converted to a pointer to the original function value. If you dereference that pointer with *, you get the same function value back again, which is immediately and implicitly converted into a pointer. And you can do this as many times as you like.
Two similar experiments you can try:
What happens if you dereference a function pointer in an lvalue context—the left-hand side of an assignment. (The answer will be about what you expect, if you keep in mind that functions are immutable.)
An array value is also converted to a pointer in an lvalue context, but it is converted to a pointer to the element type, not to a pointer to the array. Dereferencing it will therefore give you an element, not an array, and the madness you show doesn't occur.
Hope this helps.
P.S. As to why a function value is implicitly converted to a pointer, the answer is that for those of us who use function pointers, it's a great convenience not to have to use &'s everywhere. There's a dual convenience as well: a function pointer in call position is automatically converted to a function value, so you don't have to write * to call through a function pointer.
P.P.S. Unlike C functions, C++ functions can be overloaded, and I'm not qualified to comment on how the semantics works in C++.
C++03 §4.3/1:
An lvalue of function type T can be converted to an rvalue of type “pointer to T.” The result is a pointer to the function.
If you attempt an invalid operation on a function reference, such as the unary * operator, the first thing the language tries is a standard conversion. It's just like converting an int when adding it to a float. Using * on a function reference causes the language to take its pointer instead, which in your example, is square 1.
Another case where this applies is when assigning a function pointer.
void f() {
void (*recurse)() = f; // "f" is a reference; implicitly convert to ptr.
recurse(); // call operator is defined for pointers
}
Note that this doesn't work the other way.
void f() {
void (&recurse)() = &f; // "&f" is a pointer; ERROR can't convert to ref.
recurse(); // OK - call operator is *separately* defined for references
}
Function reference variables are nice because they (in theory, I've never tested) hint to the compiler that an indirect branch may be unnecessary, if initialized in an enclosing scope.
In C99, dereferencing a function pointer yields a function designator. §6.3.2.1/4:
A function designator is an expression that has function type. Except when it is the operand of the sizeof operator or the unary & operator, a function designator with type ‘‘function returning type’’ is converted to an expression that has type ‘‘pointer to function returning type’’.
This is more like Norman's answer, but notably C99 has no concept of rvalues.
It happens with a few implicit conversions. Indeed, per the C standard:
ISO/IEC 2011, section 6.3.2.1 Lvalues, arrays, and function designators, paragraph 4
A function designator is an expression that has function type. Except when it is the operand of the sizeof operator or the unary & operator, a function designator with type “function returning type” is converted to an expression that has type “pointer to function returning type”.
Consider the following code:
void func(void);
int main(void)
{
void (*ptr)(void) = func;
return 0;
}
Here, the function designator func has the type “function returning void” but is immediately converted to an expression that has type “pointer to function returning void”. However, if you write
void (*ptr)(void) = &func;
then the function designator func has the type “function returning void” but the unary & operator explicitly take the address of that function, eventually yielding the type “pointer to function returning void”.
This is mentioned in the C standard:
ISO/IEC 2011, section 6.5.3.2 Address and indirection operators, paragraph 3
The unary & operator yields the address of its operand. If the operand has type “type”, the result has type “pointer to type”.
In particular, dereferencing a function pointer is redundant. Per the C standard:
ISO/IEC 2011, section 6.5.2.2 Function calls, paragraph 1
The expression that denotes the called function shall have type “pointer to function returning void” or returning a complete object type other than an array type. Most often, this is the result of converting an identifier that is a function designator.
ISO/IEC 2011, section 6.5.3.2 Address and indirection operators, paragraph 4
The unary * operator denotes indirection. If the operand points to a function, the result is a function designator.
So when you write
ptr();
the function call is evaluated with no implicit conversion because ptr is already a pointer to function. If you explicitly dereference it with
(*ptr)();
then the dereferencing yields the type “function returning void” which is immediately converted back to the type “pointer to function returning void” and the function call occurs. When writing an expression composed of x unary * indirection operators such as
(****ptr)();
then you just repeat the implicit conversions x times.
It does make sense that calling functions involves function pointers. Before executing a function, a program pushes all of the parameters for the function onto the stack in the reverse order that they are documented. Then the program issues a call instruction indicating which function it wishes to start. The call instruction does two things:
First it pushes the address of the next instruction, which is the return address, onto the stack.
Then, it modifies the instruction pointer %eip to point to the start of the function.
Since calling a function does involve modifying an instruction pointer, which is a memory address, it makes sense that the compiler implicitly converts a function designator to a pointer to function.
Even though it may seems unrigorous to have these implicit conversions, it can be useful in C (unlike C++ which have namespaces)
to take advantage of the namespace defined by a struct identifier to encapsulate variables.
Consider the following code:
void create_person(void);
void update_person(void);
void delete_person(void);
struct Person {
void (*create)(void);
void (*update)(void);
void (*delete)(void);
};
static struct Person person = {
.create = &create_person,
.update = &update_person,
.delete = &delete_person,
};
int main(void)
{
person.create();
person.update();
person.delete();
return 0;
}
It is possible to hide the implementation of the library in other translation units and to choose to only expose the struct encapsulating the pointers to functions, to use them in place of the actual function designators.
Put yourself in the shoes of the compiler writer. A function pointer has a well defined meaning, it is a pointer to a blob of bytes that represent machine code.
What do you do when the programmer dereferences a function pointer? Do you take the first (or 8) bytes of the machine code and reinterpret that as a pointer? Odds are about 2 billion to one that this won't work. Do you declare UB? Plenty of that going around already. Or do you just ignore the attempt? You know the answer.
How exactly does dereferencing of a function pointer work?
Two steps. The first step is at compile time, the second at runtime.
In step one, the compiler sees it has a pointer and a context in which that pointer is dereferenced (such as (*pFoo)() ) so it generates code for that situation, code that will be used in step 2.
In step 2, at runtime the code is executed. The pointer contains some bytes indicating which function should be executed next. These bytes are somehow loaded into the CPU. A common case is a CPU with an explicit CALL [register] instruction. On such systems, a function pointer can be simply the address of a function in memory, and the derefencing code does nothing more than loading that address into a register followed by a CALL [register] instruction.
This question already has answers here:
Why is the size of a function in C always 1 byte?
(4 answers)
Closed 9 years ago.
I always understood that in C, func and &func were equivalent. I assume they should both be of type pointer, which is 8 bytes on my Win64 system. However, I just tried this:
#include <stdio.h>
int func(int x, int y)
{
printf("hello\n");
}
int main()
{
printf("%d, %d\n", sizeof(&func), sizeof(func));
return 0;
}
And expecting to get the output 8, 8 was surprised to get 8, 1 instead.
Why is this? What type exactly is func? It seems to be of type char or some equivalent.
What is going on here?
I compiled this with gcc -std=c99 if it makes a difference.
What type is a function name in C?
A function name or function designator has a function type. When it is used in an expression, except when it is the operand of sizeof or & operator, it is converted from type "function returning type" to type "pointer to a function returning type". (This is specified in C99, 6.3.2.1p4).
Now
sizeof(func)
is not valid C as sizeof is not allowed with an operand of function type. This is specified in the constraints of the sizeof operator:
(C99, 6.5.3.4p1 Constraints) "The sizeof operator shall not be applied to an expression that has function type or an incomplete type, to the parenthesized name of such a type, or to an expression that designates a bit-field member."
But
sizeof(func)
is allowed in GNU C.
There is a GNU extension in GNU C that allows it and in GNU C sizeof with an operand of function type yields 1:
6.23 Arithmetic on void- and Function-Pointers
[...] sizeof is also allowed on void and on function types, and returns 1.
http://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html
Given:
int func(int x, int y) { /* ... */ }
the expression func is of function type. Specifically, it's of type int(int, int), which is C's syntax for the type "function with two int parameters returning int. (You won't often see that particular syntax, since it's not common to refer to function types directly.)
In most contexts, an expression of function type is implicitly converted to a pointer to the function; in this case, the pointer is of type int(*)(int, int).
The contexts in which this implicit conversion does not occur are:
When the expression is the operand of unary &; in that case, &func yields the address of the function (just as func by itself usually does); and
When the expression is the operand of sizeof. Without this exception, sizeof func would yield the size of a function pointer. Instead, it's a constraint violation, requiring a diagnostic from the compiler.
(A side note: This conversion does happen when the function name is used in a function call. The () "operator" (the standard doesn't call it that) requires a prefix of pointer-to-function type.)
gcc happens to have a non-standard extension; it permits pointer arithmetic on function pointers and on type void*, acting like pointer arithmetic on char* pointers (i.e., it operates in units of bytes). Unfortunately, IMHO, gcc did this via a kludge, setting the size of function types and of type void to 1. That's why you get sizeof func == 1; if you enable one of the standard conforming modes (e.g., gcc -std=c99 -pedantic), you'll get a warning.
Incidentally, don't use %d to print the result of sizeof. sizeof yields a result of type size_t. If your implementation supports it (C99 or later), use %zu; if not, you need to use a cast to explicitly convert the size_t value to something that you can print. For example:
printf("%lu\n", (unsigned long)sizeof &func);
What type is a function name in C?
It's of a function type.
I always understood that in C, func and &func were equivalent
Well, they are not "equivalent". A function does, however, decay into a pointer-to-function.
I assume they should both be of type pointer
That's an incorrect assumption.
And expecting to get the output 8, 8 was surprised to get 8, 1 instead. Why is this?
Because 1. it's UB if it compiles, 2. it shouldn't even compile in first place, and as such, your program is free to do anything.
Names do not have a type in C. Some kinds of names denote entities that have type, such as typedef names, objects or functions. Other kinds of names denote entities that do not have a type, such as preprocessor symbols or goto labels. Yet other kind of names simply denote types themselves, namely typedef names.
The name of a function denotes an entity that has function type. That function type includes the return type, and (possibly incomplete) information about the parameters.
When functions are used as values, they are always manipulated as pointer-to-function types. A function as such cannot be passed around in a portable C program, but a pointer to a function can be.
Conceptually, even in a direct call like foo(), what happens is that foo, an expression denoting a function, upon evaluation is implicitly converted to a pointer-to-function value. The () function call postfix operator then invokes the function by means of this pointer.
There is a rule that an expression that has function type produces a pointer value, except if that expression is the operand of the & (address of) or of the sizeof operator. func and &func are only equivalent in the sense that they produce the same value. func produces a pointer value implicitly. &func suppresses the implicit generation of a pointer (func is the operand of & and so the conversion is suppressed), but then & takes the address.
So you can see that sizeof &func and sizeof func are different. The former takes the size of a pointer, and the latter tries to take the size of a function.
Taking the size of a function is a constraint violation in C: it requires a diagnostic from an implementation that conforms to the standard. If the program still translates and a value of 1 is produced when it is run, that is "bonus" behavior specific to your language implementation. It is not in the standard language.
Suppose there is a function pointer:
void func(float a1, float a2) {
}
void (*fptr)(float, float) = &func;
Is there any difference between these two lines (both compile and work on my compiler)?
(*fptr)(1,2);
fptr(1,2);
I suppose that the second version is just a shortcut of the first one, but want to ensure myself. And more important is it a standard behavior?
They do the same thing.
The prefix of a function call is always an expression of pointer-to-function type.
An expression of pointer type, such as the name of a declared function. is implicitly converted to a pointer to that function, unless it's the operand of a unary "&" (which yields the function's address anyway) or of sizeof (which is illegal rather than yielding the size of a pointer).
The consequence of this rule is that all of these:
&func
func
*func
**func
are equivalent. They all evaluate to the address of the function, and they can all (if suitably parenthesized) be used as the prefix of a function call.
Yes, it is standard behavior and will work in all C compilers.
Function calls are actually always made through a pointer to function:
6.5.22 "Function calls":
The expression that denotes the called function (footnote 77) shall have type pointer to function returning void or returning an object type other than an array type
As footnote 77 indicates, a 'normal' function identifier is actually converted to a pointer-to-function when a function call is expression is used:
Footnote 77:
Most often, this is the result of converting an identifier that is a function designator.
Interestingly, dereferencing a function pointer (or a function designator converted to a function pointer) yields a function designator for the function, which will be converted back to a function pointer for the function call expression. So you can dereference the function pointer (or a normal function name), but don't have to.
6.5.3.2/4 "Address and indirection operators":
The unary * operator denotes indirection. If the operand points to a function, the result is a function designator
So as far as the standard is concerned, for your examples:
(*fptr)(1,2);
fptr(1,2);
The second isn't really a shorthand - it's what the compiler expects. Actually, the first example is really just a more verbose way of saying the same thing as the second. But some people might prefer the first form as it makes it more clear that a pointer is being used. There should be absolutely no difference in the generated code.
Another consequence of the standard's wording is that you can just as well dereference a normal function name:
func(1,2);
(*func)(1,2); // equivalent to the above
Not that there's really any defensible point to doing that that I can think of.
int foo(char *c) {...}
main() {
int (*thud)(void *);
thud = (int (*)(void *))(foo);
}
What actually happens during the evaluation of the assignment?
There is a difference between the cast type and foo; the cast type is a pointer and foo is a function. So, does the compiler convert what's in '(foo)' into a pointer to foo and only then make the cast? Because nothing else seems to make sense; the other option is that the function itself is converted to a pointer to a function that gets a void* and returns an int, and as far as I know a function is a label to a piece of code in memory and thus cannot become a pointer, which is a variable.
The name of a function is a pointer when used as such. It's somewhat similar to how the name of an array is a pointer to its first element.
That being said, calling a function through a pointer with a different type than the function's actual prototype (as your example does) is undefined behavior. Don't do it.
Addendum
If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.
from section 6.3.2.3 of the C standard.
In C, absolutely nothing. It is just compiler glue to prevent you from doing something stupid. In C, the caller is responsible for maintaining the stack frame, so the cast is necessary when you invoke the function (i.e. arguments and the return value are pushed onto the stack). This makes it safe(r) since the caller's stack will not likely be mutated improperly. However, the invoked function can still mess up the caller's stack in certain rare cases.
I should clarify that the assignment copies the function pointer. But in C, all function pointers are just pointers. The type and casting is all compiler glue.
Another clarification: The standard specifies (in 6.5.2.2) that the behavior is undefined if the caller uses incompatible types. For example, casting a function which returns void into one which returns an int and then calling that function, the "returned" value is meaningless. It's a good idea to cast the function into a compatible type before calling it, or you may see unexpected results.
A pointer in C is an address, i.e. a number stored in some place. A function in C is an address to some code. Those two are one of the same.
The correct term is decay. Function foo decays to a pointer to foo before the cast. The cast itself will be a no-op on all platforms I can think of.
Note, however, that the behavior of a program containing such a cast is undefined by the C standard.
This was going to be a comment to Rick C. Petty's answer - but it doesn't fit in 300 characters.
The C standard is not very restrictive - pointers to objects (and functions aren't objects) can be converted to 'pointer to void' and back without problem. POSIX requires that pointers to functions are all the same size and can be converted to pointer to void.
POSIX 2008 - General Information - The Compilation Environment
2.12.3 Pointer Types
All function pointer types shall have the same representation as the type pointer to void. Conversion of a function pointer to void * shall not alter the representation. A void * value resulting from such a conversion can be converted back to the original function pointer type, using an explicit cast, without loss of information.
Note:
The ISO C standard does not require this, but it is required for POSIX conformance.