指针作用于函数;
通常我们声明一个指向函数的指针。用来告诉函数要是调用哪个函数。
例如;顺序数组涉及比较两个元素,以确定先后。(如果元素是数字,可以用 > 运算符;如果元素是字符串或者结构,就要调用函数去比较。
我们来进一步研究函数指针。首先我们先要知道什么是函数指针?
回顾一下,数据指针的意义:假设有一个指向int类型的指针变量,该指针存储着这个int类型变量存储在内存位置的地址。 其次,声明数据指针时,必须声明指针所指向的数据类型。
函数指针的意义:函数也有地址,因为函数的机器语言实现由载入内存的代码组成,指向函数的指针由中存储着函数代码的起始位处的地址。
声明函数指针
声明函数指针时,必须声明指针指向的函数类型。函数类型也就是函数的签名,也就是函数的返回值类型和形参的类型。例如;
TopUpper()函数类型是”带char * 类型的参数,返回值类型为void的函数“
下面声明一指针wisdom个指向该函数类型;
void (*wisdom)(char *);//wisdom是一个指向函数的指针。
从该声明中可以看出,第一个括号 表示pf是一个指向函数的指针。因此wisdom是一个参数列表为(char *),返回值为void的函数。注意:把原本的函数名TopUpper替换为表达式(*wisdom)是创建函数指针最简单的方式。所以如果想声明函数指针时就必须把*和指针名括起来。如果省略第一个圆括号就会出现截然不同的情况;
void *wisdom(char *);//此时wisdom是一个返回字符指针的函数。
总结: 想要声名一个指向特定函数类型的指针,可以先声明一个该类型的函数,然后把函数名替换成(*wisdom)的形式表达式,然后,wisdom就成为指向该类型函数的指针。
函数地址赋给指针;
声明指针函数后,可以将类型匹配的函数地址赋给指针函数,举个栗子;
void Rise(char *);
void Decline(char *);
int found(double);
void (*f)(char *);//声明函数指针
开始给函数指针传递函数地址;(函数名为函数地址)
f = Rise;//有效Rise是该类型函数的地址
f = Decline;//有效,Decline是该类型函数的地址
f = found;//无效found于该类型的指针函数不匹配
f = Rase();//无效Rase不是地址
注意注意注意:最后一条语句错误不仅仅是因为Rase()不是地址而且Rase()的返回值类型void,没有返回值,也不能在赋值语句中进行赋值。总结;(指针f可以指向其他返回值为void类型,参数为char类型的函数,不能指向其他类型的函数)
数据指针可以访问数据,那么也可以用函数指针访问函数,但是奇怪的是,有两种逻辑上不一样的语法可以这样做,下面解释:
void rise(char *);
void decline(char*);
void (*f)(char*);
char Des[]="I have red apples";
f = rise;
(*f)(Des); //rise作用于Des上(语法1)
f = decline;
f(Des); //把decline作用于mis(语法2)
看上去这两种语法都合情合理,是吧。
首先我们先来分析第一种,由于f指针指向rise函数,那么*f就相当于rise函数,所以表达式 (*f) (Des)就等同于rise (Des)。从函数 rise 和指针函数 f 的声明就可以看出rise和(*f)是等价的。
第二种 由于函数名为指针,那么函数名和指针可以互换使用,所以亦f(Des)和decline(Des)相同。
历史上,本来两个是不等价的但是最后为了和现代代码兼容就等价了(就这么个事)
总结
函数名代表函数的地址,可以把函数的地址作为参数传递给其他函数,然后这些函数就可以使用被指向的函数。如果特定的函数的地址赋给一个名为pf的函数指针,则可以通过以下两种方式调用函数: