函数指针(函数指针作为函数形参/函数类型作为函数返回类型)

函数指针是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。函数指针有两个用途:调用函数和做函数的参数

 1 #include<stdio.h>
 2 int max(int x,int y){return (x>y? x:y);}
 3 int main()
 4 {
 5     int (*ptr)(int, int);
 6     int a, b, c;
 7     ptr = max;
 8     scanf("%d%d", &a, &b);
 9     c = (*ptr)(a,b);
10     printf("a=%d, b=%d, max=%d", a, b, c);
11     return 0;
12 }

以上来自百度百科

函数指针指向的是函数而非对象。和其他指针一样,函数指针指向某种特定类型。函数的类型由它的返回类型和形参类型共同决定,与函数名无关:

bool length_compare(const string &, const string &);

该函数的类型是 bool(const string &, const string &);想要声明一个指向该函数的指针,只要用指针替换函数名即可:

 1 #include <iostream>
 2 using namespace std;
 3
 4 bool leng_compare(const string &s1, const string &s2){
 5     return s1.size() > s2.size();
 6 }
 7
 8 int main(void){
 9     //pf指向一个函数,该函数的参数是两个 const string 的引用,返回值是 bool 类型
10     bool (*pf) (const string &, const string &);//未初始化
11     return 0;
12 }

注意 *pf 两端的括号必不可少的。如果不写这对括号,则 pf 是一个返回值为 bool 指针的函数。

使用指针函数:

当我们把函数名作为一个值使用时,该函数自动地转换成指针:

#include <iostream>
using namespace std;

bool leng_compare(const string &s1, const string &s2){
    return s1.size() > s2.size();
}

int main(void){
    //pf指向一个函数,该函数的参数是两个 const string 的引用,返回值是 bool 类型
    bool (*pf) (const string &, const string &);//未初始化
    pf = leng_compare;//pf指向名为 leng_compare 的函数
    cout << &pf << endl;
    cout << *pf << endl;
    cout << pf << endl;

    pf = &leng_compare;//和上面的那条赋值语句是等价的,即取地址符是可选的
    cout << &pf << endl;
    cout << *pf << endl;
    cout << pf << endl;
    return 0;
}

此外,我们还能直接使用指向函数的指针调用该函数,无需提前解引用指针:

#include <iostream>
using namespace std;

bool leng_compare(const string &s1, const string &s2){
    return s1.size() > s2.size();
}

int main(void){
    //pf指向一个函数,该函数的参数是两个 const string 的引用,返回值是 bool 类型
    bool (*pf) (const string &, const string &);//未初始化
    pf = leng_compare;//pf指向名为 leng_compare 的函数
    bool flag1 = pf("acfjls", "fjsl");//调用leng_compare函数
    bool flag2 = (*pf)("fjlsfld", "jfs");//一个等价调用
    bool flag3 = leng_compare("fjslfjs", "jfkdl");//另一个等价调用
    return 0;
}

指向不同函数类型的指针间不存在转换规则。但是和往常一样,我们可以为函数指针赋一个 nullptr 或者值为 0 的常量表达式,表示该指针没有指向任何一个函数。

重载函数的指针:

当我们使用重载函数的指针时,上下文必须清晰地界定到底应该选用哪个函数。编译器通过指针类型确定选用哪个函数,指针类型必须与重载汉萨中的某一个精确匹配:

 1 #include <iostream>
 2 using namespace std;
 3
 4 int gel(int* x){}
 5
 6 int gel(unsigned int x){}
 7
 8 int main(void){
 9     int cnt = gel(1);//单独函数调用是可以不是精确匹配,只要能有最佳匹配即可
10     // int (*pf1)(int) = gel;//错误:形参列表不能精确匹配
11     // double (*pf2)(int*) = gel;//错误:和第一个gel函数返回类型不匹配,和第二个gel函数形参不匹配
12     int (*pf3)(unsigned int) = gel;//正确
13     return 0;
14 }

函数指针形参:

和数组类似,虽然不能定义函数类型的形参,但是形参可以是指向函数的指针。此时形参看起来是函数类型,实际上却是当成指针使用:

 1 #include <iostream>
 2 using namespace std;
 3
 4 bool length_compare(const string &, const string &){}
 5
 6 //第三个形参是函数类型,它会自动转换成指向函数的指针
 7 void max(const string &s1, const string &s2, bool pf(const string &, const string &)){}
 8 //等价声定义,显示地将形参定义成指向函数的指针
 9 // void max(const string &s1, const string &s2, bool (*pf)(const string &, const string &)){};
10
11 int main(void){
12     max("fjs", "jfls", length_compare);//把函数当作为实参使用,此时它会自动地转换成指针
13     return 0;
14 }

可以使用 typedef 定义自己的类,简化函数使用函数指针:

 1 #include <iostream>
 2 using namespace std;
 3
 4 bool length_compare(const string &, const string &){}
 5
 6 // gel1 和 gel2 是等价的函数类型
 7 typedef bool gel1(const string &, const string &);
 8 typedef decltype(length_compare) gel2;
 9
10 //gel3 和 gel4 是等价的指针类型
11 typedef bool(*gel3)(const string &, const string &);
12 typedef decltype(length_compare) *gel4;
13
14 //需要注意的是这里的 decltype 返回的是函数类型,此时不会将函数类型自动转换成指针类型,只有在 decltype 返回结果前加上 * 才能得到指针
15
16 void max(const string &s1, const string &s2, gel1){}//编译器自动将gel1转换成指针类型了
17
18 // void max(const string &s1, const string &s2, gel3){}//等价声明
19
20 int main(void){
21     max("fjs", "jfls", length_compare);//把函数当作为实参使用,此时它会自动地转换成指针
22     return 0;
23 }

返回指向函数的指针:

和数组类似,虽然不能返回一个函数,但是能返回指向函数类型的指针。然而,我们必须把返回类型写成指针的形式,编译器不会自动地将函数返回类型当成对应的指针类型处理。而想要声明一个返回函数指针的函数,可以直接声明,使用类型别名,尾置类型等:

 1 #include <iostream>
 2 using namespace std;
 3
 4 using gel1 = int(int*, int);//gel1是函数类型,不是指向函数的指针
 5 using gel2 = int(*)(int*, int);//gel2是指向函数的指针
 6 // typedef int (*gel3)(int*, int);//gel2的等价类型
 7
 8 // gel1 lou(int x);//错误:gel1是函数类型,不是指针类型
 9 gel2 lou(int x);
10 gel1* lou(int x);
11 int (*lou(int x))(int *, int);//不使用类型别名,直接声明
12 auto lou(int) -> int (*)(int *, int);//使用尾置返回类型
13
14 int main(void){
15     return 0;
16 }

使用 decltype:

当我们明确知道返回的函数是哪一个,就能使用 decltype 简化书写函数指针返回类型的过程,需要注意的是 decltype 返回的不是指针,需要添加 *,这点和数组是一样的:

 1 #include <iostream>
 2 using namespace std;
 3
 4 int gel(int *, int);
 5
 6 decltype(gel) *lou(int x);//注意这里的*不能落掉
 7
 8 int main(void){
 9     return 0;
10 }
时间: 2024-10-09 16:37:51

函数指针(函数指针作为函数形参/函数类型作为函数返回类型)的相关文章

Java中的方法(形参及实参)return返回类型

如何定义 Java 中的方法 所谓方法,就是用来解决一类问题的代码的有序组合,是一个功能模块. 一般情况下,定义一个方法的语法是: 其中: 1. 访问修饰符:方法允许被访问的权限范围, 可以是 public.protected.private 甚至可以省略 ,其中 public 表示该方法可以被其他任何代码调用,其他几种修饰符的使用在后面章节中会详细讲解滴 2. 返回值类型:方法返回值的类型,如果方法不返回任何值,则返回值类型指定为 void :如果方法具有返回值,则需要指定返回值的类型,并且在

在printf语句中调用day_name函数并把i值传送给形参n

本例中定义了一个指针型函数day_name,它的返回值指向一个字符串.该函数中定义了一个静态指针数组name.name数组初始化赋值为八个字符串,分别表示各个星期名及出错提示.形参n表示与星期名所对应的整数.在主函数中,把输入的整数i作为实参,在printf语句中调用day_name函数并把i值传送给形参n.day_name函数中的return语句包含一个条件表达式,n值若大于7或小于1则把name[0]指针返回主函数输出出错提示字符串"Illegal day".否则返回主函数输出对应

数组指针、指针数组、函数指针、指针函数 -----笔记

1.数组的四种访问方式 定义数组 a[]; 指针 *p 指向数组a; (1) 利用数组的下表进行访问 a[i]; (2) 数组名+地址的偏移量i *(a+i) (3) 利用指针 p 进行下表访问 p[i] (4) 指针p + 地址的偏移量i *(p+i) 一维数组数组名:相当于一个单指针 2. 数组指针(指针)     指针数组(数组) 函数指针(指针)     指针函数(函数)    -------->只看后边两个字就能够区分是指针还是数组或函数 _______________________

深入理解 [指针函数] 、[函数指针]、[指针的指针]、[指向指针数组的指针]

指针函数 1.指针函数是指带指针的函数,即本质是一个函数.当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需要指针或地址的表达式中. 函数返回类型是某一类型的指针: 格式: 类型标识符  *函数名(参数表) int *match(void *key_x,void *key_y); 解析:首先来说它是一个函数,只不过这个函数的返回值是一个地址值.函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针

函数指针与指针函数

一. 在学习arm过程中发现这“指针函数”与“函数指针”容易搞错,所以今天,我自己想一次把它搞清楚,找了一些资料,首先它们之间的定义: 1.指针函数是指带指针的函数,即本质是一个函数.函数返回类型是某一类型的指针 类型标识符    *函数名(参数表) int *f(x,y); 首先它是一个函数,只不过这个函数的返回值是一个地址值.函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量. 表示: float *fun();

C++函数传递指向指针的指针的应用

传递指向指针的引用假设我们想编写一个与前面交换两个整数的 swap 类似的函数,实现两个指针的交换.已知需用 * 定义指针,用 & 定义引用.现在,问题在于如何将这两个操作符结合起来以获得指向指针的引用.这里给出一个例子: // swap values of two pointers to int void ptrswap(int *&v1, int *&v2) { int *tmp = v2; v2 = v1; v1 = tmp; } 形参 int *&v1 的定义应从右

指向指针的指针做函数的参数(转载)

一. 回顾指针概念:  今天我们又要学习一个叫做指向另一指针地址的指针.让我们先回顾一下指针的概念吧!  当我们程序如下申明变量:  short int i; char a; short int * pi; 程序会在内存某地址空间上为各变量开辟空间,如下图所示.  内存地址→6     7      8     9     10     11    12    13     14    15  ---------------------------------------------------

函数指针和指针函数的区别

一. 在学习arm过程中发现这"指针函数"与"函数指针"容易搞错,所以今天,我自己想一次把它搞清楚,找了一些资料,首先它们之间的定义: 1.指针函数是指带指针的函数,即本质是一个函数.函数返回类型是某一类型的指针 类型标识符    *函数名(参数表) int *f(x,y); 首先它是一个函数,只不过这个函数的返回值是一个地址值.函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量. 表示

C-函数指针,指针函数,构造体之结构体

指针函数: 返回值是指针的函数 指针函数的定义: 一般形式: 类型说明符 *函数名(形参表){ 函数体 } 其中, 函数名之前加了’*’ 号表明这是一’指针型函数, 即返回值是一个指针. 类型说明符表示了返回的指针所指向的数据类型 函数指针: 一个函数在内存中总是占用一段连续的内存区, 而函数名就是该函数所占内存区的首地址——把函数的这个首地址(入口地址) 赋予一个指针变量, 使该指针变量指向该函数. 然后通过指针变量就可以找到并调用这个函数——这种指向函数的指针变量称为”函数指针变量” 类型说