C语言中的指针函数和函数指针

指针函数和函数指针这对词语总是让人迷惑,其实只是语法长得像,造成极易混淆。先来说明它们的区别

项目 指针函数 函数指针
本质 函数 指针
写法 int *func(int a) int (*p)(int a)
含义 函数执行完,返回一个指针 保存函数的入口地址,可以调用函数
括号位置 *和返回类型在一起,func是函数名 (*p)整体
内存 函数在代码段,返回值指针指向数据区 p变量本身在栈,存函数地址

然后逐一展开介绍两者定义和实际使用情况

一、指针函数--返回指针的函数

1、定义

本质是一个函数,这个函数的返回值是指针,一般定义形式是:

数据类型* 函数名 (参数列表);

注意:不能将具有局部作用域的变量的地址作为函数的返回值(因为局部变量的内存空间在函数返回后即被释放,而该变量也不再有效),可以返回全局、static静态变量、malloc堆内存的地址

2、主要应用

a标准库就是指针函数

b返回堆上malloc开辟的内存地址(调用方free释放)

c返回数组/结构体指针,返回对象地址

示例代码

c 复制代码
#include<stdio.h>
#include<windows.h>
#include<math.h>
int* get_max(int *a,int*b )
{
    if(*a>*b)
    {
        return a;
    }
    else{
        return b;
    }
}
int main(){
    SetConsoleOutputCP(65001);
    SetConsoleCP(65001);
    int a=10,b=20;
    int *p=get_max(&a,&b);
    printf("%d\n",*p);  
    return 0;
} 

运行结果:

二、函数指针--指向函数的指针变量

在C程序中,可以将函数地址保存在函数指针变量中,然后用该指针间接调用函数。

1、定义--

本质是一个指针变量,这个指针保存函数的地址,指向一个函数,一般定义形式是:

返回类型 (*指针名)(参数列表)

2、主要应用

a把函数作为参数传给另一个函数,内部自动调用

c 复制代码
#include<stdio.h>
#include<windows.h>
#include<math.h>

int add(int a,int b){
    return a+b;
}
int sub(int a,int b){
    return a-b;
}
int main(){
    SetConsoleOutputCP(65001);
    SetConsoleCP(65001);
    //定义函数指针p,输入是2个int,输出是1个int
    int (*p)(int,int);
    p=add;//函数名代表函数入口地址
    printf("两个数的和是%d\n",p(5,4));//等价add(5,4),结果为9
    p=sub;//函数名和&函数名,都可以表示函数的地址
    printf("两个数的差是%d\n",p(5,4));//等价sub(5,4),结果为1
    return 0;
} 

b在嵌入式、单片机大量使用函数指针作为函数表、跳转表

c 复制代码
#include<stdio.h>
#include<windows.h>
#include<math.h>
void add(int a,int b){
    printf("两个数之和是%d\n",a+b);
}
void sub(int a,int b){
    printf("两个数之差是%d\n",a-b);
}
int main(){
    SetConsoleOutputCP(65001);
    SetConsoleCP(65001);
    //函数指针数组
    void (*func[])(int,int)={add,sub};
    func[0](5,4);
    func[1](5,4);
    return 0;
} 

两个运行结果都是如下:

c、多态事项、接口封装

硬件驱动:不同硬件,统一接口,替换不同底层函数(eg:lcd显示,切换lcd1、lcd2,只需要修改函数指针,上层代码不用改动)

d、信号处理、中断回调(单片机):中断触发后执行注册好的回调函数。

当有参数时,函数指针写起来很长,工程代码常常使用typedef重命名,示例如下:

c 复制代码
#include<stdio.h>
#include<windows.h>
#include<math.h>

int add(int a,int b){
    printf("两个数之和是%d\n",a+b);
    return a+b;
}

int sub(int a,int b){
    printf("两个数之差是%d\n",a-b);
    return a-b;
}
int main(){
    SetConsoleOutputCP(65001);
    SetConsoleCP(65001);
    //定义Func_P为函数指针-类型:指向输入2个int参数,返回1个int
    typedef int (*Func_P)(int a,int b);
    Func_P p=add;
    p(1,2);
    p=sub;
    p(1,2);
    return 0;
} 

运行结果:

相关推荐
一壶浊酒..5 小时前
Scrape Webpack练习
开发语言·javascript·webpack
ZJH__GO5 小时前
网络编程v4pro--实现聊天室文件传输功能
java·服务器·网络·计算机网络
程序员黑豆5 小时前
Windows 系统 Java 环境变量配置全攻略:解决“不是内部或外部命令”
java·前端·ai编程
命运之光5 小时前
【C语言完整代码】就诊信息管理系统
java·c语言·开发语言
命运之光6 小时前
【C语言完整代码】图书管理系统:图书馆场景下的增删改查实战
c语言·开发语言
猿长大人6 小时前
C# | Serilog 新手入门
开发语言·c#·.net·log
marvelyu6 小时前
每天10分钟学会OceanBase系列(Day 20):跨机房容灾实战——构建多数据中心高可用架构
java·大数据·数据库
在世修行8 小时前
从零打造 C# 工业视觉检测系统(七):串口通信 SerialPort 封装与开发
开发语言·c#·modbus rtu·rs232/rs485
AI人工智能+电脑小能手8 小时前
大白话说Java设计模式-04-工厂方法模式(业务实战篇)
java·设计模式·工厂方法模式·架构设计·代码解耦
沫璃染墨8 小时前
《从零入门Linux系统篇(十五):系统工具篇·六——GDB调试器详解:从程序执行控制到高级调试技巧》
linux·运维·服务器·c语言·c++