C 基础——指针函数与函数指针
一、指针函数的定义
指针函数,顾名思义,返回指针的函数。其一般定义形式如下:
类型名 *函数名(函数参数列表);
其中,后缀运算符括号()
表示这是一个函数,其前缀运算符星号*
表示此函数为指针型函数,其函数返回值为指针,当调用这个函数后,将得到一个“指向返回值为…的指针(地址),类型名
表示函数返回的指针指向的类型”。
“(函数参数表列)”中的括号为函数调用运算符,在调用语句中,即使函数不带参数,其参数表的一对括号也不能省略。其示例如下:
int *pfun(int, int);
*
的优先级低于()
的优先级,因而pfun首先与后面的()
结合,也就意味着pfun是一个函数。即:
int* (pfun(int, int));
接着和前面的*
结合,说明该函数的返回值是一个指针。再前面是一个int,也即 pfun 的返回值是一个返回值为整型类型的函数。
二、函数指针
指向函数的指针;
int (*pfun)(int, int);
返回值为int
,是不可再被*
取值的;
int* (*pfun)(int, int);
==
int *pfun(int, int);
函数指针通过括号强制性的将pfun
首先与*
结合,也就意味着,pfun
是一个指针,接着与后面的()
结合,说明该指针指向的是一个函数,最后与前面的int
结合,也就意味着,该函数的返回值是int
。
虽然仅有一个括号的差别,但表示的意义却截然不同。
函数指针(如同整型指针
int*
)的本质是一个指针,只不过指向的类型不是一般的基本数据类型,而是函数,对该函数的返回值没有要求,也可以为指针;指针函数的本质是一个函数,其函数的返回值是一个指针;
三、以函数指针作为函数的返回值
分析如下的函数声明:
int (*ff(int))(int, int);
*
的优先级小于()
,ff
首先与()
结合,意味着ff(int)
的返回值为指针(这称为指针函数),再与后面的()
结合,也即该指针指向的是一个函数。
这种写法易让人产生误解,更非常难懂。一般来说,用typedef
关键字会使该声明简单易懂;
typedef int (*PF)(int, int);
typedef
是类型定义关键字,也即int (*pf)(int, int);
此时pf
是一个函数指针变量
,当使用typedef
声明后,PF
就成为了一个函数指针关键字。这样,我们便可使用PF
作为返回值来声明函数;
PF ff(int);
四、以函数指针为返回值的应有实例
求序列最值和平均值:
#include <stdio.h>
#include <assert.h>typedef double(*PF)(double *, int );double GetMin(double* seq, int sz)
{double minVal = seq[0];assert(sz > 0);for (int i = 1; i < sz; ++i)if (minVal > seq[i])minVal = seq[i];return minVal;
}double GetMax(double* seq, int sz)
{double maxVal = seq[0];assert(sz > 0);for (int i = 1; i < sz; ++i)if (maxVal < seq[i])maxVal = seq[i];return maxVal;
}
double GetAverage(double* seq, int sz)
{double sum = 0.; assert(sz > 0);for (int i = 0; i < sz; ++i)sum += seq[i];return sum / sz;
}double Unknown(double* seq, int sz)
{return 0;
}PF GetOp(char c)
{switch (c){case 'd':return GetMin;case 'x':return GetMax;case 'p':return GetAverage;default:return Unknown;}
}int main(int, char**)
{double dbData[] = { 3.1415926, 1.4142, -0.5, 999, -313, 365 };int sz = sizeof(dbData) / sizeof(dbData[0]);char c;fputs("please input the operation: ", stdout);c = getchar(); printf("%f\n", GetOp(c)(dbData, sz));return 0;
}
我们看到,由typedef
定义的函数指针类型实际上是给出一种接口规范;
References
[1] 深入理解指针函数
C 基础——指针函数与函数指针相关推荐
- go语言基础(二)函数,数组,指针,结构体
目录 函数 匿名函数 函数闭包的简单使用以及获取键盘输入 闭包加上函数多返回值 为什么闭包不会被垃圾回收 defer 内置函数panic.recover 语言变量作用域 数组 数组定义 数组+函数+宏 ...
- C语言基础知识之define宏定义表达式,undef,内存对齐,a和a的区别,数组知识点,int (*)[10] p,二维数组参数与二维指针参数,函数指针数组,常见的内存错误及对策
一.用define宏定义表达式 1.定义一年有多少秒: #define SEC_A_YEAR 60*60*24*365 //上述描述不可靠,没有考虑到在16位系统下把这样一个数赋给整型变量的时候可能会 ...
- C语言基础10——指针进阶。字符指针、指针数组、数组指针、函数指针、函数指针数组、回调函数、数组名详解、杨氏矩阵、字符串旋转
目录 字符指针 指针数组 数组指针 数组传参.指针参数 函数指针 函数指针数组 指向函数指针数组的指针 回调函数 练习 数组名的意义 指针笔试题 字符指针 字符指针的另一种使用方式 #include ...
- 【C 语言】指针 与 数组 ( 指针 | 数组 | 指针运算 | 数组访问方式 | 字符串 | 指针数组 | 数组指针 | 多维数组 | 多维指针 | 数组参数 | 函数指针 | 复杂指针解读)
相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...
- 指向成员函数的指针有什么用_指针函数,函数指针,有点懵圈了?你能分清楚吗...
指针函数和函数指针到底怎么区分? 1.前言 数组.指针,这两个词结合的顺序不同,其意义也不同. 同样的,函数.指针这两个词结合的顺序不同其意义也不同,即指针函数与函数指针的意义不同. 2.指针函数 指 ...
- 数组指针和指针数组,函数指针和指针函数,常量指针和指针常量,常量引用
一.数组指针和指针数组 1.数组指针(行指针) 首先要知道数组指针是指向数组的指针.所以数组指针本质是个指针,只不过指向一个数组而已.格式为:T (*ptr)[]. 注意:"[]" ...
- 【C/C 】浅谈C/C 中函数指针与回调函数
01.函数指针 1.1.函数指针定义 一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似.我们可以把函数的这个首地址(或称入口地址)赋予 ...
- 指针结构体函数-事实上能够这样具体理解
今天一大早登了下QQ空间,看到本科的一个学弟发表一篇日志.写关于西电微软俱乐部面试题的解答,写的非常不 错. 我也一下子起兴了,由于我以前也是被指针困惑非常久.搞不清头绪,本科到研究生.我也笔试面试不 ...
- 函数指针与回调函数、句柄
函数指针 定义: 函数指针是指向函数的指针变量. 因而"函数指针"本身首先应是指针变量,只不过该指针变量指向函数.这正如用指针变量可指向整型变量.字符型.数组一样,这里是指向函数. ...
最新文章
- java定时关机源码_java实现电脑定时关机的方法
- 用人工智能打击人工智能
- 【控制】《多智能体系统的协同群集运动控制》陈杰老师-第7章-Brunovsky 型高阶非线性多智能体系统一致性控制
- 怎么求星期几的后几天C语言,计算任何一天是星期几的C语言源代码.
- Excel 文件读取
- POJ - 3683 Priest John's Busiest Day(2-SAT+路径打印)
- 编程语言API性能大比拼
- 简历要求中“ 扎实的JAVA基础”的学习方法
- 洛谷——P1706 全排列问题
- 外键查询_详解MySQL数据库删除所有表的外键约束、禁用外键约束相关脚本
- 计算机专业方面的期刊介绍
- tp5 查询求和_TP5 Or查询的几种方法
- 2019-CS224n-Assignment1
- dagger2 使用无法自动生成dagger + component 等问题集錦
- USACO 2016 JANUARY CONTEST, BRONZE PROBLEM 3. MOWING THE FIELD(收割庄稼)
- 1995-2013年RSA大会历届主题回顾
- Java后端春秋招之旅
- How I Hacked Facebook with a Word Document
- Excel#整体增加相同行高的宏命令#
- 考试管理系统-刷题系统案题目选项编写
热门文章
- Phoenix命令及语法
- Spark SQL介绍和特点
- PAT甲级 1017 Queueing at Bank
- 荣耀play3 鸿蒙,荣耀play系列跳过2直接上3代,999元的配置还能愉快play吗?
- python实现点击按钮_python实现点击按钮修改数据的方法
- Pandas——如何更改DataFrame中的值
- LeetCode 39. 组合总和(回溯+剪枝)
- OpenGL+VS2012环境搭建
- php redis zset 延迟队列_用PHP+Redis实现延迟任务,实现自动取消订单
- Windows下Redis的使用