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
*/
/*
''为字符的标志
""为字符串的标志
[]为数组的标志
()为函数的标志
*/