当前位置: 首页 > news >正文

第7章 C语言的函数指针与指针函数 (三)

文章目录

      • 7.3 函数指针与指针函数

7.3 函数指针与指针函数

  1. 函数指针

    • 函数指针是指向函数的指针变量,其本质是一个指针变量。
    • 函数名是函数的地址,这个地址是一个函数的入口地址,而且是函数调用时使用的起始地址。
    • 当函数指针指向了一个函数,就可以通过这个指针来调用该函数,函数指针可以将函数作为参数传递给其他函数调用。
  2. 函数指针的定义

    • 函数指针变量说明的一般形式如下:

      数据类型 ( *函数指针名称 ) ( 参数说明列表 )
    • 数据类型:是函数指针所指向的函数的返回值类型;

    • 函数指针名称:符合标识符命名规则

    • 参数说明列表:应该与函数指针所指向的函数的形参说明保持一致;

    • 函数指针名称 中,*说明为指针 () 不可缺省,表明为函数的指针。

    • 例如 :

    void (*func)(intint);  // func先结合*, 因此func是一个指针, 什么类型的指针呢? 
    						  // 是函数类型的指针, 是 有2个参数,无返回值类型的函数				
    void * func  (int,int) ;  // func 先结合什么呢 ? 
    						  // 是*的优先级高, 还是() 优先级高 , 查资料可知() 的优先级比* 的优先级高
    						  // 因此 func先结合() , func( ) , func就是一个函数了 
    	                      // void *变成了修饰   , 是指针类型的函数 
    
  3. 实例92

    • 使用函数指针调用函数。
    • 源文件
    01-cbase\92-function.c
    
    • 源代码
    #include <stdio.h> 
    #include <math.h> 
    
    
    
    // 函数使用的三个步骤 
    
    // 2. 函数的声明   
    // 函数定义在main之前, 可以省略声明部分 
    
    // 1. 函数定义
    // 函数定义的三要素  函数名 , 形参 , 返回值 
    // 函数名 : add 
    // 形参   : int x , int y  
    // 返回值 : int 
    int  add(int x, int y)
    {
        return x+y ; 
    }
    int sub(int x, int y)
    {
        return x-y; 
        // ...
    }
    int mul(int x, int y)
    {
        return x*y; 
        // ...
    }
    
    int div(int x, int y)
    {
        return x/y;
        // ...
    }
    
    // x^y 计算次方 使用pow函数来计算 
    int mypow(int x, int y) 
    {
        return (int)pow(x,y);
        // ...
    }
    
    
    int main(int argc, char const *argv[])
    {
        // 3. 函数的调用 
        // 定义一个函数类型的指针 
        int (*pfunc)(int x, int y) ; // pfunc就是一个函数类型的指针, 可以保存函数的入口地址, 就是函数的首地址
        pfunc = add ; // 指针变量保存函数的入口地址 
        int ret = pfunc(10,5) ; // pfunc = add, 等价于 add(10,5);
        printf("ret = %d\n",ret);
    
        pfunc = sub;            // 指针变量保存函数的入口地址
        ret = pfunc(10, 5); // pfunc = sub, 等价于 sub(10,5);
        printf("ret = %d\n", ret);
    
        pfunc = mul;            // 指针变量保存函数的入口地址
        ret = pfunc(10, 5); // pfunc = mul, 等价于 mul(10,5);
        printf("ret = %d\n", ret);
    
        pfunc = div;            // 指针变量保存函数的入口地址
        ret = pfunc(10, 5); // pfunc = div, 等价于 div(10,5);
        printf("ret = %d\n", ret);
    
        pfunc = mypow;            // 指针变量保存函数的入口地址
        ret = pfunc(10, 5); // pfunc = mypow, 等价于 mhypow(10,5);
        printf("ret = %d\n", ret);
    
        return 0;
    }
    
    
    • ​ 运行结果
    ret = 15
    ret = 5
    ret = 50
    ret = 2
    ret = 100000
    
  4. 函数名与函数指针的理解

    • 函数名: 是函数的入口地址, 也是函数的起始地址, 同样是函数的地址
    • 例如: 实例93
    • 源文件
    01-cbase\93-function.c
    
    • 源代码
    #include <stdio.h>
    
    
    
    // 1. 函数定义
    // 函数定义的三要素  函数名 , 形参 , 返回值 
    // 函数名 : add 
    // 形参   : int x , int y  
    // 返回值 : int 
    int  add(int x, int y)
    {
        return x+y ; 
    }
    
    
    int main(int argc, char const *argv[])
    {
        int a[10]={0};
        printf("add  =%p\n",add);  // add 是函数名, 也是函数的起始地址, 同样是函数的地址 
        printf("a    =%p\n",a  );  // a   是数组名, 也是数组的起始地址, 同样是数组的地址
    
        int  (*pfunc)(int x, int y);// 定义一个函数类型的指针变量, 用来保存函数名(函数的地址)
        pfunc = add; // 把函数名赋值给函数指针变量 
        printf("pfunc=%p\n",pfunc); // 输出pfunc变量中的值
       
        int * pa = a;  // 定义一个整型指针变量, 并把数组的地址赋值给pa
        printf("pa   =%p\n",pa); // 输出pa指针变量中的值
    
    
    
        return 0;
    }
    
    
    • 运算结果
    add  =0000000000401550
    a    =000000000061FDE0
    pfunc=0000000000401550
    pa   =000000000061FDE0
    
  5. 指针函数

    • 指针函数,其本质是一个函数,函数返回是某一类型的指针。

    • 是指一个函数的返回值为地址量的函数。

  6. 指针函数定义

    • 指针函数的定义的一般形式如下:
    <数据类型>  *<函数名称>(<参数说明>)
    {
        语句序列;
    }
    
    • <数据类型> 、<函数名称>、<形式参数说明> 等与一般函数定义相同;

    • 在<函数名称>之前的*符号,说明该函数返回 一个地址量。

    • 例如 :

    int  *f(int x,int y); // f是一个函数, 一个返回值是 int* 类型的函数
    
  7. 函数指针与指针函数的区别

    • 定义不同
      • 指针函数本质是一个函数,其返回值为指针。
      • 函数指针本质是一个指针,其指向一个函数。
  • 写法不同
    • 指针函数:int* fun(int x,int y);
    • 函数指针:int (*fun)(int x,int y);
    • 指针函数的*是属于数据类型的,而函数指针的星号是属于函数名的。

相关文章:

  • apt 的 update 和 upgrade 命令的区别是什么?
  • 【从零学Python】一些工具类的使用:SummaryWriter()、tqdm()
  • 计算机毕业设计ssm+vue基本微信小程序的考试刷题及分析系统小程序
  • MMlab 官方教程链接汇总
  • win10你的设备遇到问题,需要重启的五种解决方法
  • 【MyBatis笔记12】MyBatis中二级缓存相关配置内容
  • EasyExcel 官网观看建议
  • 再苦再累也必须要弄懂的:ES6的ES Module
  • K210使用Mx-yolov3训练
  • Springboot中日志的简单使用
  • 0. SQL细节要点
  • 网络安全——Cobaltstrike
  • 架构师的 36 项修炼第07讲:高性能系统架构设计
  • 微信小程序开发03 自定义组件:怎么培养组件化思维?
  • 4.bs4 节点遍历
  • php的引用
  • [rust! #004] [译] Rust 的内置 Traits, 使用场景, 方式, 和原因
  • 【347天】每日项目总结系列085(2018.01.18)
  • 【comparator, comparable】小总结
  • angular学习第一篇-----环境搭建
  • ES6系列(二)变量的解构赋值
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • Golang-长连接-状态推送
  • isset在php5.6-和php7.0+的一些差异
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • vue自定义指令实现v-tap插件
  • 缓存与缓冲
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 如何进阶一名有竞争力的程序员?
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • # Panda3d 碰撞检测系统介绍
  • ###项目技术发展史
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (rabbitmq的高级特性)消息可靠性
  • (安卓)跳转应用市场APP详情页的方式
  • (附源码)spring boot校园拼车微信小程序 毕业设计 091617
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (九十四)函数和二维数组
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .NET 使用 XPath 来读写 XML 文件
  • .pop ----remove 删除
  • @FeignClient 调用另一个服务的test环境,实际上却调用了另一个环境testone的接口,这其中牵扯到k8s容器外容器内的问题,注册到eureka上的是容器外的旧版本...
  • @require_PUTNameError: name ‘require_PUT‘ is not defined 解决方法
  • [ai笔记4] 将AI工具场景化,应用于生活和工作
  • [C#基础]说说lock到底锁谁?
  • [C/C++]数据结构 堆的详解
  • [CSAWQual 2019]Web_Unagi ---不会编程的崽
  • [C语言]——分支和循环(4)
  • [Docker]十二.Docker consul集群搭建、微服务部署,Consul集群+Swarm集群部署微服务实战
  • [Docker]五.Docker中Dockerfile详解
  • [INSTALL_FAILED_TEST_ONLY],Android开发出现应用未安装