目录

  • 一、概述
    • 1.1 简介
    • 1.2 简单示例
  • 二、实例操作
    • 2.1 定义一个函数指针
    • 2.2 使用数组将多个函数指针存放
    • 2.3 使用枚举确定数组成员值
    • 2.4 定义一个结构体
  • 三、完整程序讲解
    • 3.1 关于函数地址的示例
    • 3.2 函数指针的嵌套运用
  • 四、其他相关链接

一、概述

1.1 简介

本文主要讲解函数指针及用法,同时实例讲解结构体和枚举。
函数指针是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。

1.2 简单示例

int Func(int x);//这一句是声明一个函数,是我们要被函数指针调用的函数,而且函数名表示函数的首地址。
int (*p) (int x);//这里定义了一个函数指针
int (*p) (int x); //里的int指的是函数的返回值,指要被调用的函数的返回值是整形。
int (*p) (int x); //里的*p指的是指向函数首地址的指针变量。
int (*p) (int x); //int x表示被调用的函数参数是一个且是整形。
p = Func;//这一句是把被调函数的首地址存在定义的指针变量里,用来指向被调函数。

二、实例操作

2.1 定义一个函数指针

typedef int (*stFunc_t)(stateCtx_t * st_ctx);  //typedef可以使用stFunc_t去申明一个函数指针

2.2 使用数组将多个函数指针存放

const stFunc_t _CleanShutDownStateFuncs[SHUTDOWN_STEP_NUM] =
{ShutDownPrepare,ShutDownStopUsrService,ShutDownStopLowTask,ShutDownAdjustSysTask
};

2.3 使用枚举确定数组成员值

typedef enum _MediaShutDownState_t
{SHUTDOWN_PREPARE = 0,SHUTDOWN_STOP_USER_SERVICE,SHUTDOWN_STOP_LOW_TASK,SHUTDOWN_ADJUST_SYS_TASK,SHUTDOWN_STEP_NUM
}MediaShutDownState_t;

2.4 定义一个结构体

typedef struct _stateMachine_t
{uint32_t sig;               // state machine signature, debugging purposeconst stFunc_t *funcs;      //成员申明一个函数指针 uint32_t nrSteps;          // # states
} stateMachine_t;

对结构体进行赋值

const stateMachine_t _CleanShutDownStm =
{INT_CHR('M', 'C', 'S', 'D'),_CleanShutDownStateFuncs,//将最开始的指针数组传入(每个成员指向设置的函数 )ARRAY_SIZE(_CleanShutDownStateFuncs)
};

三、完整程序讲解

3.1 关于函数地址的示例

void fun()
{}int main(void)
{printf("%p %p %p\n", &fun, fun, *fun);return 0;
}

这三个值的结果是一样的. 其实对于最后的那个*fun, 即使前面加上很多个*号, 其结果也不变, 即**fun, ***fun的结果都是一样的.
对于这个问题, 因为之前讲过函数是一种function-to-pointer方式, 其会自动转换成指针的类型, &fun是该函数的地址, 为指针类型, fun是一个函数, 会转换成其指针类型, 而对于*fun, 由于fun已经变成了指针类型, 指向这个函数, 所以*fun就是取这个地址的函数, 而又根据function-to-pointer, 该函数也转变成了一个指针, 所以以此类推, 这三个值的结果是相同的。

3.2 函数指针的嵌套运用

#include <stdio.h>
void test(int);
typedef void (*fp1)(int); //申明一个函数指针int main(void){const fp1 fp=test;  //指针指向test函数 printf( "the fp is %x\n", fp);(*fp)(9);//调用test函数,传入参数为9fp(9);const fp1 *fp2;//申明另外的函数指针const fp1 *fp3;//申明另外的函数指针fp3=test;//指针指向test函数 printf( "the fp2 is %x\n,the fp2 %x\n", fp2,fp3);//打印fp2,fp3指向的函数的地址值return 0;
}struct test_fp{const fp1 fp;
};void test(int a)
{printf( "%d\n", a );struct test_fp fp4;printf( "the fp4 is %x\n", fp4);
}

打印结果:

the fp * is e3a2d1c2
9
the fp4 is 0
9
the fp4 is 0
the fp2 is 0
,the *fp2 e3a2d1c2

解析:
1、fp1 、*fp和fp1 fp都是定义一个函数指针,赋值的话只能fp=test;
2、const fp1 fp;定义的函数指针地址都为0;
3、程序中的 fp( 9 ); 是直接使用函数指针 fp来调用。既然 fp已经是函数指针了,所以在类型上就不需要任何转换了。

4、(*fp)( 9 ),也是合法的函数调用。在这里,fp 是函数指针,所以*fp 是对于函数的引用,是函数类型。根据标准规定的 function-to-pointer 转换又把 *fp 由函数类型转换为了函数指针类型,所以实际上 (*fp)( 9 ),相当于 fp( 9 ),这种直接的函数指针调用方式。
5、test 函数也可这样调用:(*test)( 9 );。可以这样来理解:根据 function-to-pointer 转换规定,首先 test 由函数类型转换为函数指针,那么 *test 表示的又是函数类型,
最后又根据 function-to-pointer 转换为函数指针来调用函数。这其实和 (*fp)( 9 ); 是等价的。甚至 test 函数还可以这样调用:(**test)( 9 );、(***test)( 9 );、(****test)( 9 ); 等等,
或者函数指针形式:(**fp)( 9 );、(***fp)( 9 );、(****fp)( 9 ); 等等。对此的理解可参看上段中的分析。
从上面的分析可以看出,函数调用的时候可以使用函数指针的方式,也可以使用函数指示符的方式。不过,后者会由编译器自动转换为前者的形式,即函数指针的形式。和指向对象的指针相比,这是函数指针一个比较特殊的地方。

四、其他相关链接

1、C语言中指针、数组作为作为函数参数使用总结

2、C语言常见数据类型字节数和打印格式总结

3、C语言常用函数详细总结附示例

c语言函数指针、结构体、枚举实例(详细)解析(快速掌握)相关推荐

  1. c语言把结构体首地址放入指针,C语言基础———指针,结构体指针,函数指针

    指针基础 一 指针就是地址,地址就是指针.指针存储的是内存的地址. 二 指针的定义 1.&表示取址运算符,&a 可以取到 a 在内存中的地址;打印地址的占位符为(%p),printf( ...

  2. c语言中结构体类型定义的函数指针,结构体中定义函数指针

    结构体指针变量的定义 定义结构体变量的一般形式如下:形式1:先定义结构体类型,再定义变量struct 结构体标识符{ 成员变量列表;-};struct 结构体标识符 *指针变量名;变量初始化:stru ...

  3. Android JNI编程(六)——C语言函数指针、Unition联合体、枚举、Typedef别名、结构体、结构体指针...

    版权声明:本文出自阿钟的博客,转载请注明出处:http://blog.csdn.net/a_zhon/. 目录(?)[+] 一:函数指针 1.函数指针顾名思义就是定义一个指针变量指向一个函数,和一级指 ...

  4. c语言结构体共用体枚举实例程序,10-C语言结构体-共用体-枚举

    结构体是什么? 结构体和数组一样属于构造类型 数组是用于保存一组相同类型数据的,而结构体是用于保存一组不同类型的数组 定义结构体 在使用结构体之前必须先定义结构体类型,因为C语言不知道你的结构体中需要 ...

  5. C语言函数指针(结构体函数指针)

    文章目录 20211126 这篇讲得好 参考文章1:C语言函数指针(指向函数的指针)详解 函数指针的定义形式: returnType (*pointerName)(param list); 示例代码: ...

  6. 【C 语言】结构体 ( 结构体作为函数参数 | 结构体指针作为函数参数 )

    文章目录 一.结构体作为函数参数 二.结构体指针作为函数参数 三.完整代码示例 一.结构体作为函数参数 结构体变量 作为函数形参 , 在函数中 , 只能访问 该函数形参 , 无法修改 结构体内存 的值 ...

  7. Go语言的使用结构体、指针和方法

    结体体定义如下: type author struct{ field1 type1 field2 type2 ... } 结构体的定义格式如下: type 类型名 struct{ 字段1 字段1类型 ...

  8. c语言中定义结构体指针的作用,C语言结构体定义,使用及指针(1)

    前言 C语言中的结构体作为一大难点,并且对于需要学习数据结构的同学来说,这个结构是每次上课都会遇到的,所以,我们只有更深层次的理解结构体的知识,才能更好的掌握数据结构 结构体用处 结构体到底有什么用? ...

  9. 【Go语言刷题篇】Go完结篇|函数、结构体、接口、错误入门学习

    Go从0到入门6-Go完结篇 前言 Q1:函数-数字的阶乘 Q2:函数-绝对值 Q3:函数-加减乘除 Q4:结构体-学生信息1 Q5:结构体-学生信息2 Q6:接口-动物和老虎 Q7:错误-网络延迟 ...

  10. 江哥带你玩转C语言 | 14 - 结构体-枚举-共用体

    什么是结构体 结构体和数组一样属于构造类型 数组是用于保存一组相同类型数据的, 而结构体是用于保存一组不同类型数组的 例如,在学生登记表中,姓名应为字符型;学号可为整型或字符型;年龄应为整型;性别应为 ...

最新文章

  1. lookout筛选相同信息_信息流广告4大行业案例总结分析(不会操作那就抄吧,建议收藏)...
  2. 通过了OCP的全部考试后的感受(ZT)
  3. 异常“只能在执行Render()的过程中调用RegisterForEventValidation”的解决办法(转)...
  4. “睡服”面试官系列第四篇之字符串的扩展(建议收藏学习)
  5. UCScript——C++集成脚本
  6. Git - Pull Request工作流
  7. Mybatis与JDBC批量插入MySQL数据库性能测试及解决方案
  8. Kinetics-400数据集介绍
  9. 广东省30m二级分类土地利用数据(矢量)
  10. Android 12 行为变更,对应用产生的影响
  11. 带你领略Clean架构的魅力,腾讯T3大佬亲自讲解
  12. 我的世界java海边种子_我的世界:超稀有种子推荐,开局海边别墅+村庄,这个地图我爱了...
  13. Android 应用开发入门
  14. 介绍旅游网站建设与优化技巧
  15. 服务器显示中国移动,中国移动服务器地址是什么
  16. 闲聊MySQL(九):浅析SQL执行计划
  17. 安装坑——rational rose
  18. 【论文阅读】mmSampler: Efficient Frame Sampler for Multimodal Video Retrieval【MLSys 2022】
  19. 不稳定的排序算法记忆口诀
  20. 优秀是一种习惯,习惯却是来自于思维的境界

热门文章

  1. 4.5 拉普拉斯定理
  2. 研究生语音识别课程作业记录(三) 非特定人孤立词识别
  3. 黑马程序员——java基础---网络编程
  4. 一名渗透工程师所必备的技能(一)
  5. tensorflow中的eval的用法
  6. 苹果手机用什么无线耳机比较好?苹果耳机平替品牌推荐
  7. 电商系统-提交订单并发处理
  8. SpringBoot专栏 | SpringBoot2.x系列教程之花样配置--自定义Banner
  9. 【Spring】定时任务
  10. [转]关于iOS多线程,你看我就够了