C语言函数指针在形参列表和返回值中的函数声明写法

您所在的位置:网站首页 形参类型说明表 C语言函数指针在形参列表和返回值中的函数声明写法

C语言函数指针在形参列表和返回值中的函数声明写法

2024-07-13 05:07:57| 来源: 网络整理| 查看: 265

tags: C/C++ Pointer 写在前面

最近看网络, 发现系统调用中的信号函数的声明有点奇怪, 如下:

void (*signal(int sig, void (*func)(int)))(int);

虽然书中给出了解释, 但是奈何自己的C语言基础不好, 看着比较费劲, 下面就重新研究一下C语言中的函数指针, 包括以下的几种情况.

函数指针的声明(两种, 算上C++的话就是三种, 其实采用宏定义的方式也可以, 但是宏定义只是简单的变量替换, 不建议在这里使用);函数指针作为函数返回值时函数的声明;函数指针作为函数参数时函数的声明.

传统的这种写法(例如上面提到的signal()函数)看起来实在是不好理解, 特别是括号的嵌套法则很容易出错, 这里还是推荐先对函数指针进行声明之后再写入函数的声明中, 也相当于是一种划分子问题的思想.

函数指针的声明

先来看教科书中给出的函数指针的声明方式:(这也是最基本的一种)

类型标识符 (*指针变量名) (形参列表)

举个例子, 对于一个只返回两数之和的函数, 其形参列表当然是(int, int), 如下所示:

// 函数声明 int add(int a, int b); int add(int, int);// 可以不加形参变量名, 推荐这种写法 // 函数定义 int add(int a, int b){return a+b;}

采用基本写法声明指向这类函数的函数指针:

int (*funp) (int, int);

这里我采用了这类, 是因为对于其他函数, 只要其为一种返回值为int, 形参列表为(int, int)的函数, 那么就可以用funp这个指针指向该函数, 例如:

int minus(int a,int b){return a-b;} funp = minus;

当然, 虽然初学者经常使用基本写法来声明函数指针, 但是这种方法在比较复杂的情况中(我后面要提到的两种情况)声明容易出错, 下面来看通过给出别名的方式声明函数指针, 仍以相加函数为例:(写成大写是类型定义的变量命名规则)

typedef int (*FUNP)(int, int);

这种写法虽然看起来跟上面没有很大区别, 但是在声明函数返回值为函数指针的时候比较有用, 稍后我介绍具体的例子.

当然, 对于习惯使用C++的朋友来说, 使用using关键字指定类型别名更加方便, 上面的函数指针声明可以这样写:

using FUNP = int (*)(int, int);

这种写法与typedef的写法是等价的, 都是给出了一个FUNP类型作为函数指针的类型, 使用起来比较方便.

返回函数指针的函数的声明

仍以上面的两数相加为例, 如果这时候想定义一个新的函数func, 这个新的函数传入两个数, 但是返回值是上面定义的add()函数的函数指针, 那这个函数的声明应该怎么写呢?

先来看第一种.

基本形式

延续上面基本的函数指针声明形式, 可以写出如下的函数声明:

int add(int, int); int (*func(int, int))(int, int);

可以看出来这次的声明就比较复杂了, 在指针变量名后面还有一个括号, 为方便理解, 大家可以从内层括号往外看:

func(int, int)是函数func的带参数列表的声明形式, 其参数类型为两个int;func的返回值类型是int(*)(int, int), 即一个函数指针, 该指针所指向的函数是: **参数类型是两个int, 返回值类型是int**的函数.

下面是具体的实例代码:

#include int add(int, int); int (*func(int, int))(int, int); int main() { int a = 5, b = 5; int a1 = 3, b1 = 3; // 函数调用, `func(a, b)`返回一个函数指针 // 后面的`(a,b)`才是真正进行相加运算的形参 int ans = func(a1, b1)(a, b); printf("ans=%d\n", ans); return 0; /* a1=3 b1=3 ans=10 */ } int add(int x, int y) { return x + y; } // 返回函数指针的函数, 返回的函数指针,形参列表为两个int, 返回值为int int (*func(int a1, int b1))(int, int) { printf("a1=%d\n", a1); printf("b1=%d\n", b1); return add; }

在func函数的调用中, 为避免引起混淆, 传参时我写了两组值, 分别是a, b和a1, b1, 首先传入的a1, b1并不是真正作加法的参数, 而是仅被func内部的printf打印输出了, func(a1, b1)返回了一个函数指针, 这之后的(a, b)才是真正用作add()函数形参的两数.

这里还要注意, 声明与定义的写法框架是一样的, 但是在函数定义的时候需要给出形参变量名, 这就要注意形参变量名不能加在外部, 而是要加在func()这个括号里面, 外部(即函数体左大括号左边的小括号内)的形参类型是func返回的函数指针所指向的函数的形参列表, 刚接触函数指针时, 这一点尤其容易出错.

采用typedef定义函数指针类型

通过上面的例子可以看出, 用基本的函数指针声明方法来声明返回值为函数指针的函数的时候, 往往是很复杂的, 还要照顾到形参列表中变量名的位置, 一不小心括号套错了也会引发编译错误. 下面来看一种写法很简洁的函数声明方式, 就是通过上面介绍的采用typedef为函数指针定义新的类型(别名)的方式.

还是上面的例子, 先通过typedef给出函数指针类型的声明, 然后直接就能以类型别名FUNP作为函数的返回值类型了.

typedef int (*FUNP)(int, int); // function ptr int add(int, int); FUNP fun(int, int);

具体的代码如下:

#include typedef int (*FUNP)(int, int); // function ptr int add(int, int); FUNP fun(int, int); int main() { int a = 5, b = 5; int a1 = 3, b1 = 3; int ans = fun(a1, b1)(a, b); printf("ans=%d\n", ans); return 0; /* a1=3 */ /* b1=3 */ /* ans=10 */ } int add(int x, int y) { return x + y; } FUNP fun(int a1, int b1) { printf("a1=%d\n", a1); printf("b1=%d\n", b1); return add; }

可以看出这种写法虽然与上面基本形式等价, 但是理解起来很容易, 也不容易出错. 实际使用中还是推荐第二种写法.

函数指针作为参数的函数声明

这里就比较简单了, 直接在形参列表中做文章即可, 这里也就不赘述了. 依旧是两种写法.

基本写法 #include int add(int, int); int func(int, int, int (*)(int, int)); int main(int argc, char *argv[]) { int a = 3, b = 3; int ans = func(a, b, add); printf("ans=%d \n", ans); // ans=6 return 0; } int add(int a, int b) { return a + b; } int func(int x, int y, int (*f1)(int, int)) { return f1(x, y); } typedef写法 #include int add(int, int); typedef int (*FUNP)(int, int); int func(int, int, FUNP); int main(int argc, char *argv[]) { int a = 3, b = 3; int ans = func(a, b, add); printf("ans=%d \n", ans); // ans=6 return 0; } int add(int a, int b) { return a + b; } int func(int x, int y, FUNP f1) { return f1(x, y); } 结束语

有了上面的各类型的函数声明的分析, 相信大家已经能看出来signal()函数的声明意味着什么吧:

void (*signal(int sig, void (*func)(int)))(int);

还是用我给出的从内向外看的方法,

看函数signal()的形参列表(int sig, void(*func)(int)); 第一参数为int类型;第二参数为返回值类型为void, 形参类型为int的函数指针; 看signal()的返回值, 是一个返回值类型为void, 形参类型为int的函数指针.

看到这里, 希望大家对含有函数指针的函数声明有了一个新的认识. 如果有任何问题也欢迎大家一起交流学习~



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭