c陷阱与缺陷第二章——Syntactic Pitfalls
2.1 Understanding function declarations
Every C variable declaration has two parts: a type and a list of expression-like things called declarators.
A declarator looks something like an expression that is expected to evaluate to the given type.
For instance:
float f, g;
indicates that the expressions f and g, when evaluated, will be of type float.
Because a declarator looks like an expression, parentheses may be used freely:
float ((f));
means that ((f)) evaluates to a float and therefore, by inference, that f is also a float.
Analogously,
float *pf;
means that *pf is a float and therefore that pf is pointer to a float.
Once we know how to declare a variable of a given type, it is easy to write a cast for that type: just remove the variable name and the semicolon from the declaration and enclose the whole thing in parentheses.
Thus, since
float (*h)();
declares h to be a pointer to a function returning a float,
(float(*)())
is a cast to a pointer to a function returning a float.
Now we can analyze the following statement:
(*(void(*)())0) ();
First, we can see that
(void(*)())
is a cast to a pointer to function returning void.
So, is cast to such a pointer.
Thus, we can analyze the statement as follows:
(*fp)();
fp is a pointer to a function returning void, *fp is the function itself, so (*fp)() is the way to invoke it.