目录
函数指针
函数名和&函数名
函数指针的定义
函数指针的使用
函数指针陷阱
代码1
代码2
注意
函数指针数组定义
函数指针数组的使用
指向函数指针数组的指针
书写
终于军训圆满结束了,首先回顾一下指针进阶篇(1)主要是指针&数组的点!
C语言之指针进阶篇(1)_唐棣棣的博客-CSDN博客https://blog.csdn.net/m0_74841364/article/details/132223126?spm=1001.2014.3001.5502今天我们继续更深入的来了解指针!主要是指针&函数&数组的点!
在前面我们已经了解过字符指针,数组指针,这里我们将介绍到函数指针!
指针数组——是数组,是存放指针的数组。
数组指针——是指针,指向数组的指针。
字符指针——指向字符的指针。
整型指针——指向整型的指针。
浮点型的指针——指向浮点型的指针。
函数指针——指向函数的指针。
类比数组指针。
数组指针——指向数组的指针——存放的是数组的地址——&数组名就是数组的地址
函数指针——指向函数的指针——存放的是函数的地址——函数地址是否是&函数名呢?
那我们用代码来验证下。
#include
int Add(int x, int y)
{
return x + y;
}
int main()
{
//int x = 0;
//int y = 0;
//scanf("%d %d", x, y);
printf("%p\n", &Add);
printf("%p\n", Add);
//&函数名 就是函数的地址
//函数名 也是函数的地址
//注意函数名并没有首元素这一说法
}
&函数名和函数名,都是函数的地址。
那它们是否有什么区别和它们的类型是一样的吗?
它们没有区别,知识写法不一样。
它们两个类型是一样的。指向同一个函数,类型是相同的。
整形函数指针类型?
如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。而且函数名和&函数名均表示的就是这个地址。既然是地址我们就可以定义一个指针变量来存放,这个指针变量就叫作函数指针变量,简称函数指针。
那该怎样去写函数指针呢?
#include
int Add(int x, int y)
{
return x + y;
}
int main()
{
printf("%p\n", &Add);
printf("%p\n", Add);
int (*p)(int,int) = &Add;//更容易理解和熟悉
int (*p)(int x,int y) = &Add;
int (*p)(int x,int y) = Add;//写不写x y都可
int (*p)(int,int) = Add;
//&和x y 写不写都可
}
这个语句就定义了一个指向函数的指针变量 p。
首先它是一个指针变量,所以要有一个“*”,即(*p);
其次前面的 int 表示这个指针变量可以指向返回值类型为 int 型的函数;
后面括号中的两个 int 表示这个指针变量可以指向有两个参数且都是 int 型的函数。
所以合起来这个语句的意思就是:
定义了一个指针变量 p,该指针变量可以指向返回值类型为 int 型,且有两个整型参数的函数。
p 的类型为 int(*)(int,int)。
int (*p) (int, int);
函数返回值类型 (* 指针变量名) (函数参数列表);
定义了一个指针变量 p,该指针变量可以指向返回值类型为 int 型,且有两个整型参数的函数。p 的类型为 int(*)(int,int)。
p就是函数指针变量。
那如果写成int* p(int,int);?
*和int 结合 int* 变成了函数声明了。
函数指针的使用最长应用在转移表和回调函数 ,那我们在接下来的文章都会讲到。
#include
int Add(int x, int y)
{
return x + y;
}
int main()
{
printf("%p\n", &Add);
printf("%p\n", Add);
int (*p)(int,int) = &Add;
int ret=(*p)(3, 5);//解引用找到函数
int ret = (********p)(3, 5);//*是个摆设,写不写都可
int ret = Add(3, 5);//直接调用Add函数就是用Add函数的地址
int ret = p(3, 5);//这里也可以直接使用地址
printf("%d", ret);
}
我们有以上三种写法去调用函数 Add,但是我们不可以乱写哦!
int ret=* p(3, 5);
阅读两段有趣的代码!
我们改怎样去理解这两端代码呢?
(*(void (*)())0)();
//函数调用
图错误待修改
void (*signal(int , void(*)(int)))(int);
//函数声明
图错误待修改
代码2太复杂了,那能不能简化代码2???当然可以。
void (* signal(int, void(*)(int)))(int);
//void(*)(int) signal(int void(*)(int));❌
//重定义
typedef void(*pfun_t)(int);
pfun_t signal(int pfun_t);
注 :推荐《C陷阱和缺陷》
int(*p)(int,int)=Add;
(*p)(3,5);
p(3,5);
(*p)();
p();//不传参数
void (* signal(int,int))(int);
int(*p)(int,int);
void(*p)(int);
char * arr[5]字符指针数组——数组——存放的是字符指针
int * arr[5]整形指针数组——数组——存放的是整形指针
int(*p[5])(int,int) void(*p[5])(int,char)等等
函数指针数组——数组——存放的是函数指针(函数的地址)
把函数的地址存到一个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义呢?
int (*parr1[10]])();
int *parr2[10]();
int (*)() parr3[10];
答案是:parr1 parr1 先和 [] 结合,说明parr1是数组。
数组的内容是什么呢? 是 int (*)() 类型的函数指针。
#include
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int main()
{
int(*p1)(int, int) = &Add;
int(*p1)(int, int) = ⋐
//函数指针数组中存放的类型相同的多个元素
int(*p[])(int, int) = { &Add,&Sub };
//p是函数指针数组_存放函数指针的数组
//均是返回类型为int,函数参数是int,int类型
}
函数指针数组的用途:转移表。
使用条件:函数类型/函数参数类型必须一摸一样
#define _CRT_SECURE_NO_WARNINGS 1
//计算器
#include
void meau()
{
printf("**************************\n");
printf("** 1.add 2.sub ****\n");
printf("** 3.mul 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;
}
int main()
{
int input = 0;
int x = 0;
int y = 0;
int ret = 0;
do
{
meau();
printf("请选择>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("请输入2个操作数:");
scanf("%d %d", &x, &y);
ret = Add(x, y);
printf("ret=%d\n", ret);
break;
case 2:
printf("请输入2个操作数:");
scanf("%d %d", &x, &y);
ret = Sub(x, y);
printf("ret=%d\n", ret);
break;
case 3:
printf("请输入2个操作数:");
scanf("%d %d", &x, &y);
ret = Mul(x, y);
printf("ret=%d\n", ret);
break;
case 4:
printf("请输入2个操作数:");
scanf("%d %d", &x, &y);
ret = Div(x, y);
printf("ret=%d\n", ret);
break;
case 0:
printf("退出游戏");
break;
default:
printf("选择错误,重新选择\n");
break;
}
} while (input);
return 0;
}
能不能让代码变得简单一点?
//简化后
#include
void meau()
{
printf("**************************\n");
printf("** 1.add 2.sub ****\n");
printf("** 3.mul 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;
}
int main()
{
int input = 0;
int x = 0;
int y = 0;
int ret = 0;
//用函数指针数组
//
do
{
meau();
printf("请选择>\n");
scanf("%d", &input);
int(*p[])(int, int) = { NULL,&Add,&Sub,&Mul,&Div };
//0 1 2 3 4
if (input == 0)
printf("退出游戏\n");
else if (input > 0 && input <= 4)
{
printf("请输入两个操作数:\n");
scanf("%d %d", &x, &y);
ret = (*p[input])(x, y);
printf("ret=%d\n", ret);
// ret = p[input](x, y);//用函数指针数组的下标找到指向的函数
}
else//其他
printf("选择错误,请重新选择!\n");
} while (input);
return 0;
}
当然出了使用函数指针数组去更高效的使用计算器,下章我们将使用回调函数去高效优化计算器!
指向函数指针数组的指针是一个 指针 指针指向一个 数组 ,数组的元素都是 函数指针 。
指向整型指针数组的指针
#include
int main()
{
int a = 0;
int b = 0;
int c = 0;
int* arr[] = { &a,&b,&c };//整形指针数组
int* (*p)[3] = &arr;//p是指针,是指向整形指针数组的指针
return 0;
}
函数指针数组的指针
#include
int main()
{
int(*arr[5])(int, int) = { NULL,&Add,&Sub,&Mul,&Div };
p = &arr;//存放函数指针数组的指针
int(*(*p)[5])(int, int) = &arr;
return 0;
}
无论是函数指针&函数指针数组&函数指针数组的指针等等,可以一直延申下去!
我们在书写变量是,首先将变量p写出来,在添加其类型。
也可以从简单的函数指针的基础上修改!
✔✔✔✔✔最后,感谢大家的阅读,若有错误和不足,欢迎指正!最近的心情多做事少说话。
代码------→【gitee:https://gitee.com/TSQXG】
联系------→【邮箱:[email protected]】