Pointer to function and function type
典型例子
下面的典型的例子来源自:
1、c-faq The Clockwise/Spiral Rule
Pointer to function
+--------------------+
| +---+ |
| |+-+| |
| |^ || |
char *(*fp)( int, float *);
^ ^ ^ || |
| | +--+| |
| +-----+ |
+------------------------+
fp
就是典型的pointer to function
Function type
+-----------------------------+
| +---+ |
| +---+ |+-+| |
| ^ | |^ || |
void (*signal(int, void (*fp)(int)))(int);
^ ^ | ^ ^ || |
| +------+ | +--+| |
| +--------+ |
+----------------------------------+
signal
就是典型的function type。
对比凸显差异的例子
typedef int* Function(int*); // function pointer
typedef int* (*PointerToFunction)(int*); // pointer to function
void
in function type and function pointer
本节收录了一些使用void
的例子。
stackoverflow What does C expression ((void(*)(void))0)(); mean?
((void(*)(void))0)();
NOTE:
1、结合了pointer to function 、cast 、function invokation
So we have integer 0 type casting to this tricky type (void(*))(void)
and then executing it. Source claims that this should work, but what does it actually?
This must be one of those C jokes like #define TRUE FALSE
, I suppose.
A
This is a function expecting no arguments and returning no value:
void f(void)
This is a pointer to a function expecting no arguments and returning no value:
void (*p)(void)
This is the type of that pointer:
void (*)(void) /* just remove the p! */
This is that type in parentheses:
(void (*)(void))
This is a cast to that type (the type in parentheses, followed by a value):
(void (*)(void))0
Still with me? so far we have the integer value 0 cast to a pointer-to-function-that-takes-no-arguments-and-returns-nothing.
The cast is an expression with pointer-to-function type. When you have one of those you can call it like this:
(your expression here)(arguments to the function)
The first set of parentheses are just for precedence, and sometimes might not be needed (but this time they are). The end result:
((void (*)(void))0)(/* no args */);
Takes the value 0, casts it to pointer-to-function-expecting-no-arguments-and-returning-nothing, and calls it, supply no arguments.
A
The syntax to cast address to a function pointer and then call it would look like this:
((void (*)(void))address)();
It might be clearer to do something like this though:
void (*fptr)(void) = (void (*)(void))address;
fptr();
Said that ((void(*)(void))0)();
instruction is used to jump to 0 in firmwares usually. It is a bit improper because it actually calls in 0 instead of jumping to 0, but practically it won't make any difference (a fw hot reboot will be performed)
stackoverflow What is void(*)(void *)
[duplicate]
A
It's a function pointer.
void (*destroy)(void *data)
destroy
is a pointer to a function which returns void
and takes a void*
as an argument.
cdecl.org is a useful tool for discerning complex C declarations. Also, take a look at the spiral rule.
void(void)
在sizeof operator的例子中看到了这个声明,其中的注释说它声明的是一个function
printf("sizeof(void(*)(void)) = %zu\n", sizeof(void(*)(void)));
printf("sizeof(char[10]) = %zu\n", sizeof(char[10]));
// printf("sizeof(void(void)) = %zu\n", sizeof(void(void))); // Error: function type
它是声明的function type,可以参看Typedef Function Type
iso-9899 Typedef Function Type
There's no need to typedef pointers to function types, typedefing a function type makes things clearer.
'function' is a pointer to a function type:
typedef int (*function)(int a, int b);
function pointer;
The alternative of a non-pointer function type is:
typedef int function(int a, int b);
function *pointer;
Code Sample
#include <stdio.h>
int add(int a, int b) {
return a + b;
}
int sub(int a, int b) {
return a - b;
}
typedef int function(int a, int b);
int call_function(function *p, int a, int b) {
return p(a, b);
}
int main(void) {
int sum;
sum = call_function(&add, 10, 5);
printf("add: %d\n", sum);
sum = call_function(&sub, 10, 5);
printf("sub: %d\n", sum);
return 0;
}
Function pointer and type aliasing
Function pointer and type aliasing有时候是比较容易混淆的,下面是一些例子:
csdn 详解virtual table
#include <iostream>
using namespace std;
class Base
{
public:
virtual void f()
{
cout << "Base::f" << endl;
}
virtual void g()
{
cout << "Base::g" << endl;
}
virtual void h()
{
cout << "Base::h" << endl;
}
};
int main()
{
typedef void (*Fun)(void);
Base b;
Fun pFun = NULL;
cout << "虚函数表地址:" << (int*) (&b) << endl;
cout << "虚函数表的第一个函数地址:" << (int*) *(int*) (&b) << endl;
// Invoke the first virtual function
pFun = (Fun) *((int*) *(int*) (&b));
pFun();
}
// g++ test.cpp -Wall -pendatic
1、上述例子就是混合了pointer to function、type aliasing的,如果熟练掌握,非常可能会理解错误
2、第一次看到: (int*) *(int*) (&b)
时,我以为 (int*) *(int*)
是pointer to function passing pointer to int and return pointer to int,这是错误的,,正确的pointer to function的写法如下:
int* (*PointerToFunction)(int*)
它的准确含义是:
a、(int*) (&b)
转换为 int*
类型
b、读取值: *(int*) (&b)
c、(int*) *(int*) (&b)
将读取的值,再转换为 int*
类型