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;
} 

运行结果:

相关推荐
SunnyDays10115 分钟前
Java 拆分 Word 文档教程:按页、分页符和分节符拆分
java·word·分页·拆分
彧azz6 分钟前
Java学习记录:判断语句
java·笔记·学习·算法
企业数字化笔记10 分钟前
一批相同的电脑怎么建账?数量管理、单件编码和拆分规则
java·后端·电脑
君顾119 分钟前
本地城市社区家政物业联动系统源码:架构设计与派单联动实战
java·开发语言·健身房
hai_android21 分钟前
Android 组件化开发实践
android·java·kotlin
MayBaymax22 分钟前
MongoDB 基础概念
java·数据库·mongodb
AI编码进化论30 分钟前
云IDE介绍:环境模板化、Agent上云,云IDE该怎么选
开发语言·ide·人工智能·团队开发·ai编程
晴天的雨.99235 分钟前
[C++算法]盛最多水的容器(双指针算法)
开发语言·c++·算法
泡海椒39 分钟前
jquick-pdf 文本元素实战:段落、行内文本、制表符用法详解
java·开发语言·pdf
摇滚侠39 分钟前
《Spring Boot 3:高级与架构设计》第 1 章 元编程与元信息 个人理解 1
java·spring boot·笔记·后端