函数指针如何理解?
int add(int x, int y) {
int z = x + y;
return z;
}
int a = 10;
int b = 20;
printf("%d\n", add(a, b));
printf("%p\n", &add);// 打印函数的地址(函数指针就是存放函数的地址)
printf("%p\n", add); // 也是函数的地址;和数组一样&arr arr,取地址和函数名都是函数地址
// 那么如何存储呢?
// 和数组指针类似
int (*p)[10];
int (*p)(int, int) = add;
(*p)(2, 3); // (*p)代表add
函数指针的使用
void print(char* str) {
printf("%s\n", str);
}
void (*p) (char*) = print;
(*p)("helloworld");
有关函数指针的两个经典例子
如果把这两个例子仔细琢磨搞懂的话,函数指针基本上就可以理解了,下面给出例子和分析,有助于理解
跟着下面的步骤一步一步看,看完会大有帮助!
(*(void(*)())0)();
- 首先对于函数指针,
void (*p) (char*)
的理解,这里的p
就是函数指针,指向的函数的参数是char*
,返回值类型是void
- 现在把
p
去掉,则说明void(*)(char*)
是一种数据类型,叫做函数指针类型- 类比于
int a
;这种定义变量,对于函数指针类型的变量,则需要把定义的变量名和*
放在一起,也就是void(*p)(char*)
- 那么接下来进行分析
- 首先是个
0
,这个0
的前面是被()
括起来的,所以我们认为这是一个强制类型转换,形如(int) 10
- 所以
(void(*)())
是一个数据类型。对于void(*p)()
,说明p
是一个函数指针,指针指向的函数的参数是空,返回值类型是void
,也就是说(void(*)())
是一个函数指针类型- 加上
0
,就是把0
强制转换成函数指针类型,就是把0转换成某个地址,就是把这个0
转换成某个函数的地址- 也就是说这个
0
现在是个地址。- 然后
*
对这个地址解引用,得到fun
,再加上()
,fun()
,就是去调用0
地址处的这个函数了
void (*signal(int, void(*)(int)))(int);
- 首先,
signal()
这是一个函数,其参数为int
和void(*)(int)
- 第二个参是一个函数指针类型,指针指向参数为
int
,返回类型为void
的函数地址- 也就是说,函数名是
signal
,函数参数是这两个,那么函数的返回类型是什么呢?- 对于函数来说,去掉函数名和参数,剩下的就是函数返回类型,剩下的是
void(* ) (int)
是一个函数指针类型- 关于剩下的这部分,为什么不直接
void(*)(int) signal...
这样写??- 这是因为,对于函数指针,我们定义变量时,是
void(*p)(int)
,表示定义了一个函数指针变量p
- 我们参照定义整形变量
int p
;如果这两个我们都把p
拿掉,剩下的就是变量的数据类型了,所以对于函数指针类型,定义的时候要把这个变量写在括号里面。- 另外,我们使用
typedef
简化一下代码,有点像换元法
- 重新命名函数指针也要注意,不能直接命名
typedef void(*)(int) p_fun;
而是要这样写–>typedef void(* p_fun)(int);
此时的意思就是p_fun
就是void(*)(int)
的意思- 而此时就是
p_fun(int, p_fun);
就是上面代码的意思- 所以这个代码意思是定义了一个函数
- 函数名是
signal
- 函数的参数有两个,一个是
int
,一个函数指针类型,这个函数指针指向参数为int
,返回类型为void
的函数地址- 函数的返回类型也是一个函数指针类型,这个函数指针类型是指向一个参数为
int
,返回值类型为void
的指针