可以定义函数指针,指向某个类型相同的函数,下面小程序就是一个简单例子
#include<stdioh>
int Add(int a,int b)
{
return (a+b);
}
void main(void)
{
int (p)();//定义函数指针
int a=4,b=3;
p=Add;//指向Add函数,注意返回值统一
printf("a+b=%d\n",p(a,b));//使用函数指针进行调用
}
是的,由于指向函数的指针的类型是与函数的参数类型及数量还有返回类型相匹配的,所以一个函数指针只能指向重载函数的诸多版本中的一个版本。例如:
int func(int x); / 声明一个函数 /
int func(int x,int y);/重载函数/
int (f) (int x); / 声明一个函数指针 /
f=func; / 将func函数的首地址赋给指针f,此时f将指向第一个函数的地址而不是第二个函数 的地址/
因为重载函数的多个函数体不仅地址不同,而且类型也不同。
在程序运行中,函数代码是程序的算法指令部分,它们和数组一样也占用存储空间,都有相应的地址。可以使用指针变量指向数组的首地址,也可以使用指针变量指向函数代码的首地址,指向函数代码首地址的指针变量称为函数指针。
1.函数指针定义
函数类型 (指针变量名)(形参列表);
“函数类型”说明函数的返回类型,由于“()”的优先级高于“”,所以指针变量名外的括号必不可少,后面的“形参列表”表示指针变量指向的函数所带的参数列表。
例如:
int (f)(int x);
double (ptr)(double x);
在定义函数指针时请注意:
函数指针和它指向的函数的参数个数和类型都应该是—致的;
函数指针的类型和函数的返回值类型也必须是一致的。
2.函数指针的赋值
函数名和数组名一样代表了函数代码的首地址,因此在赋值时,直接将函数指针指向函数名就行了。
例如,
int func(int x); / 声明一个函数 /
int (f) (int x); / 声明一个函数指针 /
f=func; / 将func函数的首地址赋给指针f /
赋值时函数func不带括号,也不带参数,由于func代表函数的首地址,因此经过赋值以后,指针f就指向函数func(x)的代码的首地址。
3.通过函数指针调用函数
函数指针是通过函数名及有关参数进行调用的。
与其他指针变量相类似,如果指针变量pi是指向某整型变量i的指针,则p等于它所指的变量i;如果pf是指向某浮点型变量f的指针,则pf就等价于它所指的变量f。同样地,f是指向函数func(x)的指针,则f就代表它所指向的函数func。所以在执行了f=func;之后,(f)和func代表同一函数。
由于函数指针指向存储区中的某个函数,因此可以通过函数指针调用相应的函数。现在我们就讨论如何用函数指针调用函数,它应执行下面三步:
首先,要说明函数指针变量。
例如:int (f)(int x);
其次,要对函数指针变量赋值。
例如: f=func; (func(x)必须先要有定义)
最后,要用 (指针变量)(参数表);调用函数。
例如: (f)(x);(x必须先赋值)
指针函数
一个函数不仅可以带回一个整型数据的值,字符类型值和实型类型的值,还可以带回指针类型的数据,使其指向某个地址单元。
返回指针的函数,一般定义格式为:
类型标识符 函数名(参数表)
int f(x,y);
其中x,y是形式参数,f是函数名,调用后返回一个指向整型数据的地址指针。f(x,y)是函数,其值是指针。
通过分析可得
函数指针是一个指向函数的指针,而指针函数只是说明他是一个返回值为指针的函数,
函数指针可以用来指向一个函数。
typedef void (pFunc)(void); //定义函数指针类型
const pFunc pf; // 定义 函数指针常量 只能指向一个函数 不能更改
函数在内存中有一个物理位置,而这个位置是可以赋给一个指针的。一零点函数的地址就是该函数的入口点。因此,函数指针可被用来调用一个函数。函数的地址是用不带任何括号或参数的函数名来得到的。(这很类似于数组地址的得到方法,即,在只有数组名而无下标是就得到数组地址。)
怎样说明一个函数指针变量呢
为了说明一个变量 fn_pointer 的类型是"返回值为 int 的函数指针", 你可以使用下面的说明语句:
int (fn_pointer) ();
为了让编译器能正确地解释这句语句, fn_pointer 必须用括号围起来。若漏了这对括号, 则:
int fn_pointer ();
的意思完全不同了。fn_pointer 将是一个函数名, 其返回值为 int 类型的指针。
2:函数指针变量
在C语言中规定,一个函数总是占用一段连续的内存区, 而函数名就是该函数所占内存区的首地址。 我们可以把函数的这个首地址 ( 或称入口地址 ) 赋予一个指针变量, 使该指针变量指向该函数。然后通过指针变量就可以找到并调用这个函数。我们把这种指向函数的指针变量称为 " 函数指针变量 " 。
函数指针变量定义的一般形式为:
类型说明符 ( 指针变量名 )();
其中 " 类型说明符 " 表示被指函数的返回值的类型。 "( 指针变量名 )" 表示 "" 后面的变量是定义的指针变量。 最后的空括号表示指针变量所指的是一个函数。
例如: int (pf)();
表示 pf 是一个指向函数入口的指针变量,该函数的返回值 ( 函数值 ) 是整型。
下面通过例子来说明用指针形式实现对函数调用的方法。
int max(int a,int b)
{
if(a>b)return a;
else return b;
}
main()
{
int max(int a,int b);
int(pmax)();
int x,y,z;
pmax=max;
printf("input two numbers:/n");
scanf("%d%d",&x,&y);
z=(pmax)(x,y);
printf("maxmum=%d",z);
}
从上述程序可以看出用,函数指针变量形式调用函数的步骤如下:
1> 先定义函数指针变量,如后一程序中第 9 行 int (pmax)(); 定义 pmax 为函数指针变量。
2> 把被调函数的入口地址 ( 函数名 ) 赋予该函数指针变量,如程序中第 11 行 pmax=max;
3> 用函数指针变量形式调用函数,如程序第 14 行 z=(pmax)(x,y); 调用函数的一般形式为: ( 指针变量名 ) ( 实参表 ) 使用函数指针变量还应注意以下两点:
a 函数指针变量不能进行算术运算,这是与数组指针变量不同的。数组指针变量加减一个整数可使指针移动指向后面或前面的数组元素,而函数指针的移动是毫无意义的。
b 函数调用中 "( 指针变量名 )" 的两边的括号不可少,其中的 不应该理解为求值运算,在此处它只是一种表示符号。
3:指针型函数
前面我们介绍过,所谓函数类型是指函数返回值的类型。 在C语言中允许一个函数的返回值是一个指针 ( 即地址 ) ,这种返回指针值的函数称为指针型函数。
定义指针型函数的一般形式为:
类型说明符 函数名 ( 形参表 )
{
…… / 函数体 /
}
其中函数名之前加了 "" 号表明这是一个指针型函数,即返回值是一个指针。类型说明符表示了返回的指针值所指向的数据类型。
如:
int ap(int x,int y)
{
…… / 函数体 /
}
表示 ap 是一个返回指针值的指针型函数, 它返回的指针指向一个整型变量。下例中定义了一个指针型函数 day_name ,它的返回值指向一个字符串。该函数中定义了一个静态指针数组 name 。 name 数组初始化赋值为八个字符串,分别表示各个星期名及出错提示。形参 n 表示与星期名所对应的整数。在主函数中, 把输入的整数 i 作为实参, 在 printf 语句中调用 day_name 函数并把 i 值传送给形参 n 。 day_name 函数中的 return 语句包含一个条件表达式, n 值若大于 7 或小于 1 则把 name[0] 指针返回主函数输出出错提示字符串 "Illegal day" 。否则返回主函数输出对应的星期名。主函数中的第 7 行是个条件语句,其语义是,如输入为负数 (i<0) 则中止程序运行退出程序。 exit 是一个库函数, exit(1) 表示发生错误后退出程序, exit(0) 表示正常退出。
应该特别注意的是函数指针变量和指针型函数这两者在写法和意义上的区别。如 int(p)() 和 int p() 是两个完全不同的量。 int(p)() 是一个变量说明,说明 p 是一个指向函数入口的指针变量,该函数的返回值是整型量, (p) 的两边的括号不能少。
int p() 则不是变量说明而是函数说明,说明 p 是一个指针型函数,其返回值是一个指向整型量的指针,p 两边没有括号。作为函数说明, 在括号内最好写入形式参数,这样便于与变量说明区别。 对于指针型函数定义,int p() 只是函数头部分,一般还应该有函数体部分。
main()
{
int i;
char day_name(int n);
printf("input Day No:/n");
scanf("%d",&i);
if(i<0) exit(1);
printf("Day No:%2d-->%s/n",i,day_name(i));
}
char day_n
ame(int n)
{
static char name[]={ "Illegal day",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"};
return((n<1||n>7) name[0] : name[n]);
}
本程序是通过指针函数,输入一个 1 ~ 7 之间的整数, 输出对应的星期名。指针数组的说明与使用一个数组的元素值为指针则是指针数组。指针数组是一组有序的指针的集合。指针数组的所有元素都必须是具有相同存储类型和指向相同数据类型的指针变量。
指针数组说明的一般形式为: 类型说明符 数组名 [ 数组长度 ]
其中类型说明符为指针值所指向的变量的类型。例如: int pa[3] 表示 pa 是一个指针数组,它有三个数组元素, 每个元素值都是一个指针,指向整型变量。通常可用一个指针数组来指向一个二维数组。 指针数组中的每个元素被赋予二维数组每一行的首地址,因此也可理解为指向一个一维数组。图 6—6 表示了这种关系。
int a[3][3]={1,2,3,4,5,6,7,8,9};
int pa[3]={a[0],a[1],a[2]};
int p=a[0];
main()
{
int i;
for(i=0;i<3;i++)
printf("%d,%d,%d/n",a[i][2-i],a[i],((a+i)+i));
for(i=0;i<3;i++)
printf("%d,%d,%d/n",pa[i],p[i],(p+i));
}
本例程序中, pa 是一个指针数组,三个元素分别指向二维数组 a 的各行。然后用循环语句输出指定的数组元素。其中 a[i] 表示 i 行 0 列元素值; ((a+i)+i) 表示 i 行 i 列的元素值; pa[i] 表示 i 行 0 列元素值;由于 p 与 a[0] 相同,故 p[i] 表示 0 行 i 列的值; (p+i) 表示 0 行 i 列的值。读者可仔细领会元素值的各种不同的表示方法。 应该注意指针数组和二维数组指针变量的区别。 这两者虽然都可用来表示二维数组,但是其表示方法和意义是不同的
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)