知识点:指向函数的指针(线性表会再遇到)

本文深入解析C语言中函数指针的概念与应用,包括函数指针的定义、使用方法及作为形参的实例。通过具体示例,展示如何利用函数指针实现灵活的函数调用,适用于希望深化理解C语言高级特性的开发者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、指向函数的指针的定义及分析

int (*p)();

更加确切的定义方案:函数类型 (*指针变量名称)(形参类型表);

假设p是一个能够指向“这样类型的函数”的指针变量:int fun1(int, int);

对于能够指向上述类型的函数的指针变量的确切定义如下:int (*p)(int, int);

 

对于上述变量声明,可以这样理解:

    由于(*p)在括号的作用下,紧密结合,仅此,应将*和p视为一个整体,然后,将(int, int)与int结合,形成:int(int, int)       *p;

按照对变量的定义的普遍原则(类型  变量名称;),可以知道,p指针变量的指类是int(int, int)。其实,int(int, int)中出现的”()”,说明了这种类型其实就是“函数”,而且是:拥有两个int类型的参数,且返回值类型为int的函数(们)。

 

2、关于函数名称的说明

函数名称的本质是:该函数的首地址常量

C语言源程序中的函数,通过C编译软件对其进行编译后,将形成一段由二进制代码组成的“代码段”,这个代码段在被执行时(前)也会被调入内存。也就是说,函数最终也会以二进制数的形式,在内存中占用一段连续存储空间。当然,由于每个函数中的代码数量等不同,其所占用的内存空间大小也就不同了。但这个问题不影响每段函数代码都存在一个首地址,即,该代码段的第一条指令的首地址。而这个首地址在C源程序代码角度,就是以函数名称的形式存在的!

 

​​​​​​​ 3、指向函数的指针变量指类问题

指针的指类,对于指针的操作,起到决定性的作用。

比如,指针加/减整型量,简单的说:指针+1,会使指针的指向发生偏移,且偏移量取决于指类类型长度。

但是,对于指向函数的指针而言,由于上述所说,函数的长度(最终的二进制代码数量)是不确定的,因此,对于指向函数的指针,不讨论指针加/减整型值的问题。

 

​​​​​​​4、关于()的说明

函数调用的过程,通常是以()作为基本语法结构的。

fun(123)

fabs(x)

sqrt(2.0)

strcpy(s2, s1)

等等

上述都是关于函数的调用。

那么说明,只要存在类似“用户标识符(…)”,这就是一次函数调用。

对于fun(123),实质上是调用了首地址的值为fun的函数;

或者说,以fun为首地址值,对这个首地址处的二进制内容,当成一条指令进行操作。

 

5、指向函数的指针变量的使用方法

见下面例子

6、指向函数的指针变量作为形参

首先定义一个函数:void fun(int a, int b, int (*p)(int, int));

上述的函数声明,第三个参数“int (*p)(int, int)”,实际上就是定义了一个指向函数的指针形参变量

 

若依然如前所述,事先定义如下函数:

int add(int, int);

int sub(int, int);

接着,在其它函数中,进行如是的调用:

{

fun(3, 4, add);

}

上述的fun()函数调用的第三个实参:add,是函数add()的函数名称,且,后面没有”()”,说明该实参是add()函数的首地址值。

与其对应的形参变量,按照形参与实参“值传递”的关系,相当于执行了:int (*p)(int, int) = add;的操作。

该操作的结论是,让形参变量p,指向add()函数。

 

接着,fun()函数内部执行如下操作:

void fun(int a, int b, int (*p)(int, int))

{

    p(a, b);

}

表面上这调用的是一个名字为p的函数,实际上调用的是p所指向的函数:add()函数!

 

对于上面的操作,假设fun()函数部分的代码不更改,只要更改对fun()函数的调用的实参,就可以实现调用不同的函数的目的!

fun(3, 4, sub);

fun(3, 4, mul);

fun(3, 4, div);

当然要把mul,div看成是函数名称!

 

//指向函数的指针

#include<stdio.h>

int add(int a, int b);
int sub(int a, int b);
int fun(int a, int b, int (*funP)(int, int));    //灵活调用



int fun(int a, int b, int (*funP)(int, int)){
	return funP(a,b);
}

int sub(int a, int b){
	printf("**********现在正在执行减法功能************  ");
	return a-b;
}

int add(int a, int b){
	printf("**********现在正在执行加法功能************  ");
	return a+b;
} 

void main(void){
	int (*p)(int, int);

	p = add;                  
// 函数名称的本质:函数名称本质上是该函数的入口地址常量(指针常量)
//这里需要特别注意:add后面没有()!这说明,add在这个情况下,只表明其所对应的函数的首地址值!而非对add函数的调用!
//使得p指针的值,就是add函数的首地址!
	printf("%d\n", p(13, 4));   // ( 被解释为 call汇编指令 是函数的人口地址
//p(13, 4),其实,这可以看成:调用以p的值为首地址的那个字节开始的指令。

	p = sub;
	printf("%d\n", p(13, 4));

	printf("%d\n", fun(13, 4, sub));

}
/*
int **p;       => int*    *p;
int ar[3][4];  => int[4]  ar[3];
int *p[10];    => int*    p[10];    理解:[]的优先级大于*,故p和[]结合
int (*p)();    => int()   *p;       p指向一个函数,函数的返回值类型为int
*/

/*
''为字符的标志
""为字符串的标志
[]为数组的标志
()为函数的标志
*/


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安安csdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值