C语言基础入门48篇_38_函数指针与typedef(函数指针即指向函数的指针、函数指针定义int (*pfn)(int)、typedef给数据类型起别名,起到的作用一致、typedef简化函数指针)

整篇看完是不是还不知道函数指针怎么用来调用函数,请参考:C++57个入门知识点_17 类的访问权限及C语言模拟类的封装C++57个入门知识点_18_ 类的大小+成员函数性质+this指针C++57个入门知识点_18_ 类的大小+成员函数性质+this指针

1. 函数指针的定义

函数就是在内存中的一段机器码,也是有地址的,函数名即为函数的首地址/使用&函数名也可以得到函数地址

#include <stdio.h>

void fun()
{
	printf("hello, world\r\n");
}

int main(int argc, char* argv[])
{
	printf("%p\r\n,%p\r\n", fun,&fun);
	return 0;
}

运行结果:打印出函数的首地址
在这里插入图片描述

函数指针: 既然有地址,就可以定义指针存储该地址,存储函数(首)地址的指针,称为函数指针

函数指针的定义有些特别,它是一个动作,比如,定义一个可以指向返回值为int,有一个int参数的函数的指针,声明如下:

#include <stdio.h>

int fun(int arg)
{
    printf("hello, world\r\n");
}

int main(int argc, char* argv[])
{
    int(*pfn)(int) = NULL;
    pfn = fun;
    return 0;
}

1.1 函数指针的声明

函数指针的声明,可以按以下步骤完成:

  • 先写出目标函数的原型 int fun(int arg)
  • 将目标函数的函数名改为函数指针变量名 int *pfn(int)
  • 为“*”号和函数名加括号 int (*pfn)(int)
  • 函数指针的初始化 int (*pfn)(int)=&fun或者int (*pfn)(int)=&fun

按照上述过程对之前的程序进行修改:

  • 利用int (*pfn)(int)=&fun进行初始化
#include <stdio.h>

int fun(int arg)
{
	printf("hello, world\r\n");
	return 0;
}

int main(int argc, char* argv[])
{
	int(*pfn)(int) = NULL;
	pfn = &fun;
	printf("%p\r\n,%p\r\n", fun, pfn);
	return 0;
}

运行结果:
在这里插入图片描述

  • 利用int (*pfn)(int)=fun进行初始化
#include <stdio.h>

void fun()
{
	printf("hello, world\r\n");
}

int main(int argc, char* argv[])
{
	void(*pfun)() = fun;
	printf("%p,%p\r\n", fun, pfun);
	return 0;
}

运行结果:两者的指针地址一致
在这里插入图片描述

1.2 函数指针的复杂性

前面我们定义的函数指针变量名是在声明中间,这是在之前很少见的,这会导致广泛组合指针从而变得复杂。

想象一下,如果我们定义了一个函数,其参数是一个函数(指针),返回值也是一个函数(指针),原型分别为:

  • 参数:无参数,无返回值
  • 返回值:有一个int参数,有一个int返回值
    最终完成声明的代码类似如下:
#include <stdio.h>
#include <signal.h>

void FunArg()
{
    printf("我是没有参数没有返回值的函数\r\n");
}

int FunReturn(int arg)
{
    printf("我是int参数,int返回值的函数\r\n");
    return 0;
}
//参数是void (* pArg)(void),返回值是带有int参数的int类型的函数指针
int(*MyFunction(/*参数是一个函数指针*/void (* pArg)(void) ))(int)
{
    printf("我是参数及返回值都是函数的函数\r\n");
    return FunReturn;
}

int main(int argc, char* argv[])
{
    MyFunction(FunArg);
    return 0;
}

运行结果:
在这里插入图片描述
此部分理解可以参考链接:C++57个入门知识点_番外2_C++中指针函数、函数指针和返回值为函数指针的函数

因为C语言中函数指针的变量名不处于最末尾,所以函数指针类型组合在一起,显得非常怪异

为了简化,我们可以使用typedef语法。

2. typedef

typedef是声明别名的关键字,我们可以使用typedef,为类型起别名。(重点是类型
基本语法是:typedef <原类型名> <新别名>

2.1 新别名的效果与原类型名效果一样

typedef int MYINT;

int main(int argc, char* argv[])
{
    MYINT value = 5;
    return 0;
}

使用typedef可以增强代码的可读性。

2.2 typedef应用于函数指针

特别是对于函数指针而言,函数指针起别名较为特殊,它没有所谓原类型名,typedef之后加的标识符就是新的别名。void FunArg()-->void (*FunArg)()-->typedef void (*PFN_ARG)()
比如,使用typedef简化我们之前的代码:

#include <stdio.h>
#include <signal.h>

void FunArg()
{
    printf("我是没有参数没有返回值的函数\r\n");
}

int FunReturn(int arg)
{
    printf("我是int参数,int返回值的函数\r\n");
    return 0;
}

typedef void(*PFN_ARG)(void);
typedef int(*PFN_RETURN)(int);

PFN_RETURN MyFunction(PFN_ARG arg)
{
    printf("我是参数及返回值都是函数的函数\r\n");
    return FunReturn;
}

int main(int argc, char* argv[])
{
    MyFunction(FunArg);
    return 0;
}

运行结果:
在这里插入图片描述
代码的功能与之前完全一样,但是可读性增强了很多。

3. C/C++中的函数指针使用方法(必看)

以下实例中展示了C/C++中的函数指针的定义及使用方法。

函数指针的定义及使用方法:

  • 定义函数指针数据类型Calc:先写(*Calc)表示要定义的函数指针类型名为Calc,然后按照函数定义,定义形参和返回值
  • 最后通过typename定义为一种数据类型
  • 使用:(1)先定义函数指针变量Calc funcPoint1 = &Add;(2)调用:funcPoint1(a, b)
#include <iostream>

//定义函数指针数据类型Calc
//先写(*Calc)表示要定义的函数指针类型名为Calc,然后按照函数定义,定义形参和返回值
//最后通过typename定义为一种数据类型
//使用:(1)先定义函数指针变量Calc funcPoint1 = &Add;(2)调用:funcPoint1(a, b)
typedef int(*Calc)(int a, int b);

int Add(int a, int b)
{
	return a + b;
}

int Sub(int a, int b)
{
	return a - b;
}


int main()
{
	int a = 100;
	int b = 50;

	Calc funcPoint1 = &Add;
	Calc funcPoint2 = &Sub;

	printf("Add=%d\n", Add(a, b)); //直接调用
	printf("AddPoint=%d\n", funcPoint1(a, b)); //间接调用
	printf("Sub=%d\n", Sub(a, b));
	printf("SubPoint=%d\n", funcPoint2(a, b));
	
	return 0;
}

可以看到使用直接调用和函数指针间接调用的结果是一样的。
在这里插入图片描述

4. 学习视频地址: 函数指针与typedef

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十月旧城

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值