深入理解C语言的函数指针的定义和使用

函数指针的定义

   函数指针就是指向代码入口地址的指针,是指向函数的指针变量。所以“函数指针”本身是一个指针变量,并且该指针指向的是函数。C语言在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量之后,就可以用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是一致的。函数指针有两个用途:调用函数做函数的参数

函数指针的声明和使用

   函数指针的声明方法为:

数据类型标志符  (指针变量名) (形参列表);

“函数类型”说明函数的返回类型,由于“()”的优先级高于“*”,所以指针变量名外的括号必不可少,后面的“形参列表”表示指针变量指向的函数所带的参数列表。
例如:

int function(int x, int y);		/*声明一个函数*/
int(*f)(int x, int y);			/*声明一个函数指针*/
f = &function;					/*将function 函数的首地址赋给指针f*/
f = function;					/*将function 函数的首地址赋给指针f*/

注意点
1. 赋值时函数function不带括号,也不带参数,由于函数名 function就代表函数的首地址,因此经过赋值以后,指针 f 就指向函数function(int x, int y) 的代码的首地址。
2. 为什么使用 f = &function 和 f = function都可以进行赋值呢?这是因为在C语言中,函数名被编译之后其实就是一个地址,所以这两种用法没有本质的差别。
3. 函数指针的原型(参数和返回值)必须要和指向的函数是一致的。所以,通常,要声明指向特定类型的函数的指针,可以先编写这种函数的原型,然后用(*pf)替换函数名,这样pf就是这类函数的指针。

示例代码
char * fun(char * p1, char * p2)
{
	int i = 0;
	i = strcmp(p1, p2);

	if (0 == i)
	{
		printf("true\n");
		return p1;
	}
	else
	{
		printf("false\n");
		return p2;
	}
}
void main()
{
	char *(*pf)(char *p1, char *p2);

//	pf = &fun;
	pf = fun;
	(*pf)("aa", "bb");
//	(*pf)("bb", "bb");

	while (1);
}
函数指针数组

根据函数指针的表达式

int(*pf)(int x, int y);			/*声明一个函数指针*/

把pf这个指针存储在一个数据里面,

int(*pf[10])(int x, int y);			/*声明一个函数指针数组*/

这是一个数组,数组名为 pf ,数组内存储了10个指向函数的指针。这些指针指向一些返回值类型为int, 参数也为int的字符的指针的函数。

函数指针数组示例代码
char *fun1(char *p)
{
	printf("%s\n", p);
	return p;
}

char *fun2(char *p)
{
	printf("%s\n", p);
	return p;
}

char *fun3(char *p)
{
	printf("%s\n", p);
	return p;
}

int main()
{
	char *(*pf[3])(char *p);

	pf[0] = fun1;		//可以直接用函数名
	pf[1] = &fun2;		//可以用函数名加上取地址符
	pf[2] = &fun3;

	pf[0]("fun1");
	pf[1]("fun2");
	pf[2]("fun3");

	while (1);
}
函数指针数组的指针

函数指针数组的指针定义:

char *(*(*pf)[3])(char * p);

注意,这里的 pf 和上一节的 pf 就完全是两码事了。上一节的 pf 并非指针,而是一个数组名;这里的 pf 确实是实实在在的指针。这个指针指向一个包含了 3 个元素的数组;这个数字里面存的是指向函数的指针;这些指针指向一些返回值类型为指向字符的指针、参数为一个指向字符的指针的函数。

示例代码
char *fun1(char *p)
{
	printf("%s\n", p);
	return p;
}

char *fun2(char *p)
{
	printf("%s\n", p);
	return p;
}

char *fun3(char *p)
{
	printf("%s\n", p);
	return p;
}

int main()
{
	char * (*a[3])(char *p);
	char * (*(*pf)[3])(char * p);
	pf = &a;

	a[0] = fun1;
	a[1] = &fun2;
	a[2] = &fun3;

	pf[0][0]("fun1");
	pf[0][1]("fun2");
	pf[0][2]("fun3");

	while (1);
}
(void()())0)()的解析
1. void (*)(), 可以明白这是一个函数指针类型。这个函数没有参数,没有返回值。
2. (void(*)())0,这是将0强制转换为函数指针类型。这个函数没有参数,没有返回值。
3. (*(void(*)())0),这是取0地址开始的一段内存里面的内容,其内容就是保存在首地址为0的一段区域内的函数。
4. (*(void(*)())0)(),这是函数调用。
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页