前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >什么?回调函数是什么东西?啊?这里面的函数指针,还有那个指针数组,数组指针又是什么?

什么?回调函数是什么东西?啊?这里面的函数指针,还有那个指针数组,数组指针又是什么?

作者头像
薛定谔方程难
发布2024-01-23 16:13:38
1060
发布2024-01-23 16:13:38
举报
文章被收录于专栏:我的C语言我的C语言

出淤泥而不染,濯清涟而不妖。——周敦颐

1、回调函数

1、回调函数从定义以上理解

回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数 时,被调⽤的函数就是回调函数。回调函数不是由该函数的实现⽅直接调⽤,⽽是在特定的事件或条 件发⽣时由另外的⼀⽅调⽤的,⽤于对该事件或条件进⾏响应。 那我们想要理解到底怎么才算是回调函数,光是看定义肯定是不够用的,我们得结合实际才能有足够深入的了解。

2、回调函数的使用和加深理解

代码语言:javascript
复制
int add(int a, int b)
{
	return a + b;
}
int sub(int a, int b)
{
	return a - b;
}
int mul(int a, int b)
{
	return a * b;
}
int div(int a, int b)
{
	return a / b;
}
void calc(int(*pf)(int, int))
{
	int ret = 0;
	int x, y;
	printf("输⼊操作数:");
	scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("ret = %d\n", ret);
}
int main()
{
	int input = 1;
	do
	{
		printf("*************************");
		printf(" 1:add*********2:div*****");
		printf(" 3:mul*********0:exit****");
		printf("*************************");
		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;
}

在这句话中的这一段,是最重要的。也是回调函数的使用,从而避免了冗长的代码。

代码语言:javascript
复制
void calc(int(*pf)(int, int))
{
	int ret = 0;
	int x, y;
	printf("输⼊操作数:");
	scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("ret = %d\n", ret);
}`

利用这句话,减少了在不同case情况下,每次都要写的这段代码。

代码语言:javascript
复制
int x, y;
	printf("输⼊操作数:");
	scanf("%d %d", &x, &y);

3、引言开始补充

当然,如果现在回来看这里的使用回调函数,看那句定义的话,肯定能更深的理解这句话。 把函数的指针当作为参数传递给另一个函数时,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数。 除此之外,还必须掌握另一个很重要的并且容易出错的地方,那就是,函数指针的使用。 并且,在这里我们也可以感受到,地址的作用,如果这里没有地址的话,那将不再可能实现直接的调用。 那从这里不经想起,数组指针,指针数组那些有些模糊的定义。

2、补充

2、1指针类型

其实指针类型不知有数组,还有简单的,更容易理解的整型指针,字符指针等基本的指针。例子的话就不举了,但是要注意的是在char*的使用时,写为这样子

代码语言:javascript
复制
const char* ptr="hello world";

认为把整个都存起来,但是其实只是把这段字符串的首字符的地址放在了指针ptr中。

2、1、1好题,绝对好题!

代码语言:javascript
复制
#include<stdio.h>
int main()
{
	char str1[] = "hello";
	char str2[] = "hello";
	const char* str3 = "hello";
	const char* str4 = "hello";
	if (str1 == str2)
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");

	if (str3 == str4)
		printf("str3 and str4 are same\n");
	else
		printf("str3 and str4 are not same\n");

	return 0;
}
在这里插入图片描述
在这里插入图片描述

那为什么,str1和str2是不同的呢,其实就是因为,在创建不同的数组的时候,是在不同位置开辟的,所以即使是数组名,是h,看上去好像是一样的,但是,那本质这段话的意思其实是在内存中开辟的空间的地址,两个数组也不可能重复开辟一段空间,所以,str1和str2不可能相等。 那为什么str3和str4是相等的呢? 那是因为str3和str4是指针,指向开辟的一段空间的首字母地址,并且常量字符串是不会被修改的,而且也不会为两个指针,就把一个常量,开辟两个空间,计算机一定会节省空间的。

2、2数组指针

我们可以先由(2、1)中的内容,知道什么指针是怎么表示的,那么数组指针呢?应该是可以推断出其实就是存放数组的指针,那么数组也是有不同的大小小的,那有怎么表示的呢?

代码语言:javascript
复制
int* p1[10];
int (*p2)[10];

可以根据前面的写法猜一猜,感受一下,到底哪一个更像是数组指针? 注意:[]的优先级是高于*的。 正确的答案其实是p2那个表达形式,因为是指针,所有用(*p)来确保,先是指针,然后才轮到数组。 那么这句话是什么意思呢? 意思就是,一个p2的指针指向一个整型数组,指向一个大小是10个整型的数组。

2、3指针数组

这里,也可以通过以前讲过的整型数组来帮助我们理解。那么其实数组指针就是存放指针的数组。 再根据上面一段中,展示的优先级,其实是可以更好的理解这里就是先是数组,然后才轮到指针的。

在这里插入图片描述
在这里插入图片描述

总结:其实分清主谓语也可以帮助区别,就比如说好孩子,好是形容词,而孩子才是真正重要的主语。所以数组指针,就是指针,用来指向数组的。而指针数组,就是一个数组,用来存放指针的。

2、4函数指针

函数指针和数组名其实差不多,当是直接用函数名的时候就是函数的首地址,而&函数名就是整个函数的地址。

在这里插入图片描述
在这里插入图片描述

当然,在这里,x和y都是可以不用写出来的,写也是可以的。 下面来一段使用函数指针的例子。

代码语言:javascript
复制
#include <stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int(*pf3)(int, int) = Add;

	printf("%d\n", (*pf3)(2, 3));
	printf("%d\n", pf3(3, 5));//两种写法都是可以的
	return 0;
}
2、4、1拓展
在这里插入图片描述
在这里插入图片描述

这是啥意思呢? 其实可以从里面向外面去看,要抓住里面的*符号,其实这就是一个函数指针,只不过是一个空的名字,并且函数还没有参数。而向外看,使用了void的,就是把这函数强制类型转换。并且又因为内部函数没有参数,所以在最后的一个空里面,也是没有参数。这就是这段大妈的全部含义了。

在这里插入图片描述
在这里插入图片描述

那这句话呢? 其实应该是看成两部分,可以认为是代码的“复合函数”。 整体上来看,应该是

代码语言:javascript
复制
void (*)(int )

那么第一段括号内,就是关于signal的函数的声明 包含了两个成分,第一个是int类型,而第二个是void(*)(int)的函数

2、5函数指针数组

根据前面提到过的帮助判断的方法,可以也对这种进行判断。就比如下面这几个,来判断看看哪个是真正的指针数组。

在这里插入图片描述
在这里插入图片描述

parr1是真正的函数指针数组。 那么这些有什么用呢? 其实在下面一段就可以用到了!

2、6转移表

请看下面代码!

代码语言:javascript
复制
#include <stdio.h>
int add(int a, int b)
{
	return a + b;
}
int sub(int a, int b)
{
	return a - b;
}
int mul(int a, int b)
{
	return a * b;
}
int div(int a, int b)
{
	return a / b;
}
int main()
{
	int x, y;
	int input = 1;
	int ret = 0;
	int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表
	do
	{
		printf("*************************\n");
		printf(" 1:add 2:sub \n");
		printf(" 3:mul 4:div \n");
		printf(" 0:exit \n");
		printf("*************************\n");
		printf("请选择:");
		scanf("%d", &input);
		if ((input <= 4 && input >= 1))
		{
			printf("输⼊操作数:");
			scanf("%d %d", &x, &y);
			ret = (*p[input])(x, y);
			printf("ret = %d\n", ret);
		}
		else if (input == 0)
		{
			printf("退出计算器\n");
		}
		else
		{
			printf("输⼊有误\n");
		}
	} while (input);
	return 0;
}

这里就是用到了函数指针数组!! 同时,那个就是转移表!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-01-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、回调函数
    • 1、回调函数从定义以上理解
      • 2、回调函数的使用和加深理解
        • 3、引言开始补充
        • 2、补充
          • 2、1指针类型
            • 2、1、1好题,绝对好题!
              • 2、2数组指针
                • 2、3指针数组
                  • 2、4函数指针
                    • 2、4、1拓展
                  • 2、5函数指针数组
                    • 2、6转移表
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档