指针3

68 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情


6. 函数指针

引例:

int add(int x,int y)
{
	return x + y;
}
int main()
{
	&add;
	return 0;
}

对于函数的地址应该怎么储存呢?那就需要用函数指针类型进行接收。 对于上面的代码,我们可以这样写 int (*p)(int,int) 对于上面这个可以这么理解: ==*== 告诉我们P是个指针,从后面的小括号可以看出是个函数,函数的参数有两个,都是int 类型的,返回类型是int

下面这样进行使用:

	int(*p)(int,int)=&add;
	(*p)(1, 2);
	(**p)(1, 2);
	p(1, 2);
	add(1, 2);

我们发现上面这3种都正确,说明p变量前面的星号没有任何用处,p就相当与add。

看下面的这个代码可以更好的理解:我们发现打印的结果相同

	printf("%p\n",add);
	printf("%p\n", &add);

在这里插入图片描述

  • 看着两个表示的是什么:
  • (*(void (*)())0)()
  • void (*signal(int , void(*)(int)))(int) 我们一点一点拆分看
(*(void (*)())0)(); 
1.void (*)()这是一个函数指针类型,无参数,返回类型为空(void2.(void (*)())0这个是强制类型转换,把0强转为函数指针类型

3.*解引用变成函数,调用函数,函数无参数


void (*signal(int , void(*)(int)))(int);

1.void(*)(int)这是一个函数指针类型,返回类型为空,参数为int类型的

2.signal(int , void(*)(int))这是一个函数,函数名为signal,
参数有俩个,分别为int类型和函数指针类型。

3.函数要有返回类型,去掉signal(int , void(*)(int)),就是该函数的返回类型
该函数的类型为void (*)(int),函数指针类型。

对这个函数可以进行一下好看的改变
typedef void (*v_i)(int)
然后这样写:v_i signal(int,v_i);这样看着是不是非常舒服

7. 函数指针数组

函数指针数组 是个数组,里面的元素是是函数指针

给个例子:

void f1()
{}
void f2()
{}
int main()
{
	void (*p[2])()={f1,f2};
	这个就是函数指针数组,
	这样理解p先和[]结合说明p是一个数组,数组有2个元素,
	每个元素的个数是void (*)()函数指针类型
	return 0;
}

8. 指向函数指针数组的指针

指向函数指针数组的指针 它是一个指针,指向一个数组,数组的每个元素是函数指针类型

看下面的这个代码:

void f1()
{}
void f2()
{}
int main()
{
	void (*p[2])()={f1,f2};
	void(*(*p1)[2])()=&p;
	p1就是一个函数指针数组的指针
	return 0;
}

9. 回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。 回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应

下面有个例子:

void f1()
{}
f(int a,void (*p)())
{
	p();
}
int main()
{
	int a;
	f(a, f1);
	把f1函数作为参数传给f函数,通过函数指针来调用f1函数。
	return 0;
}

10. 小型计算器项目(对7,8,9等知识点的运用)

#include <stdio.h>
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 menu()
{
	printf("****		请选择			   ****\n");
	printf("**** 1.加			2.减 **********\n");
	printf("**** 3.乘           4.除 **********\n");
	printf("************* 0退出 ***************\n");
}
f(int (*p)(int, int))
{
	int a, b;
	printf("请输入两个整数:>");
	scanf("%d%d", &a, &b);
	printf("结果为%d\n", p(a, b));
}
int main()
{

	int n;
	int (*gather[5])(int, int) = { 0,add,sub,mul,div };
	该函数指针数组里面存的是各个函数的地址,首个元素设置为0,
	方便用下标访问
	do
	{
		menu();
		该函数打印菜单,供用户选择
		scanf("%d", &n);
		if (n == 0)
		{
			printf("退出程序\n");
		}
		else if (n > 0 && n < 5)
		{
			f(gather[n]);
			这就是一个回调函数
		}
		else
		{
			printf("选择错误请从新选择\n");
		}
	} while (n);
	return 0;
}

运行的基本情况如下: 在这里插入图片描述