目录
对于指针的一些总结:
5. 函数指针
代码1解释:
代码2解释:
指针变量:本质上就是用来存放地址的变量。
数组指针:指向数组的指针,是用来存放数组的地址的。
(1)去掉指针变量名,就是这个指针变量的类型
如:int* p = &a;去掉p,指针p的类型:int*
int(*prr)[10] = &arr;去掉prr,指针prr的类型:int(*)[10]
(2)去掉 * 和指针变量名,就是这个指针指向的变量的类型如:int* p = &a;去掉*和p,指针p指向的变量a的类型:int
int(*prr)[10] = &arr;去掉*和prr,指针prr指向的数组的类型:int [10]可以说,指针变量的类型 = 指针指向的那个变量的类型 + 一个*(*是加在指针变量名前这个位置的)
函数指针:指向函数的指针,是用来存放函数的地址的。
函数指针介绍如图:
如何通过对函数指针p1解引用找到这个函数,调用这个函数呢?
那么之前我们是如何调用函数的呢?对比图如下:
而且,我们会发现:
在获得函数地址时,&和不加&都可以;
在通过函数名调用函数时,*和不加*都可以。
#include
//函数的声明
int Add(int x, int y)
{
return x + y;
}
int main()
{
int (*p1)(int, int) = &Add;
int (*p2)(int, int) = Add;
//在获得函数地址时,&和不加&都可以
int ret1 = (*p1)(3, 5);
int ret2 = p2(3, 5);
//在通过函数名调用函数时,*和不加*都可以
printf("%d\n", ret1);//8
printf("%d\n", ret2);//8
return 0;
}
阅读两段有趣的代码:
//代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int);
先看代码1
这段解释用到的知识如下:
一、 指针的使用:
1、可以通过解引用指针变量名
2、通过解引用指针变量中存放的内容
这两种方法适用于所有类型的指针。
整形指针的使用:
函数指针的使用:(用于函数的调用)
二、 函数指针的类型和它指向的函数息息相关
指向的函数是:void test( ),则函数指针类型是:void(*)()
指向的函数是:int Add(int x,int y),则函数指针类型是:int(*)(int,int)
三、关于强制类型转换:
等号左右类型要一致,所以强制类型转换时,是转换成等号左边的类型
如:
void(*p4)() = (void(*)())0;
而且,通过 要强制类型转换成的类型 void(*)(),可知函数指针类型是 void(*)() 通过函数指针的类型 void(*)() 可知p4指向的函数大概是这样的:void test( )
四、指针的使用,函数指针的类型,强制类型转换三个知识点的综合应用
在整形指针上的应用:
在函数指针上的应用:
这样就得到了 (*(void(*)())0)(),所以说(*(void(*)())0)()是一次函数调用,调用的是0作为函数地址处的函数。
同理,(*(int(*)(int,int))0)(2,3) 这个代码也是一次函数调用,调用的是0作为函数地址处的函数,这个函数大概的样子为:int Add(int x,int y)
//代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int);
再看代码2
但是这样的代码可读性特别差。
因为函数指针类型void(*)(int)两次被用到,可以用typdef把类型进行重命名,
对这个函数指针类型进行重命名的格式为 typedef void(*重命的名)(int)
上面的代码2就可以写成这样:
typedef void(*pf_t)(int);//这样写才对,意思是把void(*)(int)类型重命名成pf_t
#include
int main()
{
pf_t signal(int, pf_t);
return 0;
}
函数指针的应用:
(1)
(2)真正的函数指针的应用(写一个简单版计算器)
//写一个计算器
//加法、减法、乘法、除法
#include
void menu()
{
printf("*******************************\n");
printf("******* 1. add *********\n");
printf("******* 2. sub **********\n");
printf("******* 3. mul **********\n");
printf("******* 4. div **********\n");
printf("******* 0. exit **********\n");
printf("*******************************\n");
}
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x * y;
}
int Div(int x, int y)
{
return x / y;
}
//计算
void calc(int(*pf)(int,int))
{
int x = 0;
int y = 0;
int ret = 0;
printf("请输入操作数:>");
scanf("%d %d", &x, &y);
ret = pf(x, y);
printf("%d\n", ret);
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
calc(Add);
break;
case 2:
calc(Sub);
break;
case 3:
calc(Mul);
break;
case 4:
calc(Div);
break;
case 0:
printf("退出计算器\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}