C语言函数指针详解

C语言函数指针

一、什么是函数指针

1.理解函数指针

​ 函数指针,首先根据他的名称我们就大概可以了解到他是一个指针,是什么样的指针呢?是和函数有关的一种特殊的指针。

​ 我们知道 int*p 是指向int型变量的指针,char*p是指向char型变量的指针,那么不难理解,函数指针就是一个指向函数的指针。

	int arr[10]={
   0};
	int *p = arr;

​ 我们知道,在数组中数组名就是首元素的地址。

​ 那么试着猜猜看,函数的地址是什么样的情况呢。

​ 我们不妨打印一下看看结果是什么样的。

int add(int x, int y)
{
   
	return x + y;
}
int main()
{
   
	printf("%p\n",&add);
	printf("%p\n",add);
	return 0;
}

​ 结果如下:

C语言函数指针详解_第1张图片

​ 结论:函数的函数名就是函数的地址。

2.如何定义函数指针以及使用

​ 搞清楚了函数的地址,和函数指针的作用,那么如何去定义一个 函数指针呢?

​ 首先,函数有三大要素:函数名、函数参数、函数返回类型、函数指针是一个指针,所以首先我们先保证函数名先和*号结合,因为在c语言运算符的运算顺序中,[]的优先级高于*,所以我们使用()来解决这个问题:(*pf),之后我们考虑add函数的参数,int x,int y,是两个整型参数,所以我们可以写出来 (*add)(int int),返回类型是 int型,所以完善后我们得到:

int (*pf)(int int)=add;

​ 我们可以得到一个定义函数指针的格式:返回类型 (*指针变量名)(函数参数类型)=函数名;

​ 那么定义好一个函数指针,该如何通过指针访问的方式去调用函数呢?

​ 我们知道,想要通过指针访问元素内容,需要通过*来解引用访问,由此推断可以这样使用函数指针:(*pf)(x,y)。

​ 但是其实在函数指针调用时,pf左边这个*号并无实际的意义,加或不加对结果都不会有影响,这使我们使用函数指针更加方便 :pf(x,y);便可以使用add函数。

3.加深理解函数指针

​ 理解了函数指针的概念后,我们通过两段复杂的函数指针代码来加深理解。

//代码1:	
(*void(*)()0)();

//代码2:
void(*signal(int,void(*)(int)))(int);

​ 这两段代码摘自《C缺陷和陷阱》

​ 第一眼看到两段代码,头痛欲裂,无从下手,想要理解这两段代码,需要先理解类型的概念:

​ 我们知道:

char*pf;
// 指针变量pf的类型是char*
int *pi;
// 指针变量pi的类型是int*
int(*parr)[10];
// parr是一个数组指针,其类型是int(*)[10];
// 根据上述例子,我们不难得出,指针变量的类型就是将指针变量名去掉后剩余的部分
void(*pf)();
// 我们去掉指针变量名pf可以得到 void(*)()就是这个函数指针的类型

​ 那我们就不难理解第一行代码了:

  • 首先(*某类型 0)是将0强制类型转化为了某类型,这串代码中是将0强转为void(*)( )类型的一个函数指针。
  • 其次 外边的括号其实是通过函数指针对函数的一次调用,解引用0地址,去0地址处的这个函数,被调用的函数是无参,返回类型是void。

​ 那我们来看第二段代码:

  • 根据上面的规则void(*)(int)是一个函数指针的类型。

  • 函数名为signal,参数有两个一个是int型参数,另一个则是void(*)(int)类型的函数指针。

  • 那么最外层的一定是指针函数的返回类型:void(*)(int)。

  • 所以这段代码其实是函数指针的一次声明:signal函数有两个参数,第一个是int类型,第二个是void()(int)的函数,返回值的类型是void()(int)函数指针类型。

    这么看来其实这两段代码也不过如此,我们在分析这种复杂函数指针代码的时候,只要抓住三大要素,函数的函数名,参数以及返回值,那所有的问题其实都不复杂。

二、函数指针数组

1.如何理解函数指针数组

​ 数组是存放相同类型数据的空间,我们知道指针数组可以用来存放多个指针,例如:

int* arr[5]

你可能感兴趣的:(c语言)