一、认识函数指针

如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。而且函数名表示的就是这个地址

函数指针的定义方式为:
函数返回值类型 (* 指针变量名) (函数参数列表);

函数指针的定义就是将“函数声明”中的“函数名”改成“(*指针变量名)
两端的括号不能省略,括号改变运算符的优先级,省略括号*将与前面的返回值类型结合表示返回值为指针类型

判断一个指针变量是指向变量的指针变量还是指向函数的指针变量呢?首先看变量名前面有没有“”,如果有“”说明是指针变量;其次看变量名的后面有没有带有形参类型的圆括号,如果有就是指向函数的指针变量,即函数指针,如果没有就是指向变量的指针变量。

int Func(int x);   /*声明一个函数*/
int (*p) (int x);  /*定义一个函数指针*/
p = Func;          /*将Func函数的首地址赋给指针变量p*/

赋值时函数 Func 不带括号,也不带参数。由于函数名 Func 代表函数的首地址,因此经过赋值以后,指针变量 p 就指向函数 Func() 代码的首地址了

使用:

int Max(int, int);  //函数声明int(*p)(int, int);  //定义一个函数指针int a, b, c;p = Max;  //把函数Max赋给指针变量p, 使p指向Max函数printf("please enter a and b:");scanf("%d%d", &a, &b);c = (*p)(a, b);  //通过函数指针调用Max函数

重点关注:c = (*p)(a, b); //通过函数指针调用Max函数

延伸:
1.定义函数指针类型:
typedef int (*fun_ptr)(int,int);
2.声明变量,赋值:
fun_ptr max_func=max;
也就是说,赋给函数指针的函数应该和函数指针所指的函数原型是一致的。
3.使用
max_func(a,b);

指针函数:返回值为指针的函数
函数指针数组
为函数指针数组赋值有两种方式:静态定义和动态赋值。

  1. 静态定义
    在定义函数指针数组的时候,已经确定了每个成员所对应的函数。例如:
void(*Array[])(void)={Stop,Run,Jump};

从根本上讲函数指针数组依然是数组,所以和数组的定义类似,由于是静态赋值,[ ]里面的数字可以
省略。这个函数指针数组的成员有三个。

  Array[1]();//执行Run函数
  1. 动态赋值
    也可以先定义一个函数指针数组,在需要的时候为其赋值。为了还原其本来面目,我们先对这个执行特定类型的函数指针进行类型重定义,然后再用这个新数据类型来定义数组。如下:
typedef void(*Funcint)(void);//此类型的函数指针指向的是无参、无返回值的函数。Funcint Array[32];//定义一个函数指针数组,其每个成员为Funcint类型的函数指针Array[10]=INT_TIMER0;//为其赋值Array[10]();//调用函数指针数组的第11个成员指向的函数

二、解读TivaWare头文件

文件路径:ti\TivaWare_C_Series-2.1.4.178\driverlib\rom.h

//*****************************************************************************
//
// Pointers to the main API tables.
//
//*****************************************************************************
#define ROM_APITABLE ((uint32_t *)0x01000010)
#define ROM_VERSION (ROM_APITABLE[0])
#define ROM_UARTTABLE ((uint32_t *)(ROM_APITABLE[1]))
#define ROM_SSITABLE ((uint32_t *)(ROM_APITABLE[2]))
#define ROM_I2CTABLE ((uint32_t *)(ROM_APITABLE[3]))
#define ROM_GPIOTABLE ((uint32_t *)(ROM_APITABLE[4]))
#define ROM_ADCTABLE ((uint32_t *)(ROM_APITABLE[5]))
……

本指针表为指针的宏定义。
((uint32_t *)(ROM_APITABLE[1]))
将指针地址(ROM_APITABLE[1]) 强制类型转换为(uint32_t *)指针
指针表图示如下:

ROM中API表从地址0x0100010开始,每4个字节存一个uint32_t型数据,指向一个子表的首地址

以rom.h 头文件中关于GPIO函数的定义为例:

#if defined(TARGET_IS_TM4C123_RA1) ||
defined(TARGET_IS_TM4C123_RA3) ||
defined(TARGET_IS_TM4C123_RB1) ||
defined(TARGET_IS_TM4C123_RB2) ||
defined(TARGET_IS_TM4C129_RA0) ||
defined(TARGET_IS_TM4C129_RA1) ||
defined(TARGET_IS_TM4C129_RA2)
#define ROM_GPIOIntTypeGet
((uint32_t (*)(uint32_t ui32Port,
uint8_t ui8Pin))ROM_GPIOTABLE[4])

#endif

  • 定义芯片型号TARGET_IS_TM4C123_RB1的作用,这里是一个条件编译
  • 宏定义 ROM_GPIOIntTypeGet 是一个强制类型转换:
    (
    (uint32_t ( * ) (uint32_t ui32Port, uint8_t ui8Pin))
    ROM_GPIOTABLE[4]
    )
    把 ROM_GPIOTABLE[4] 转换为一个函数指针 uint32_t ( * ) (uint32_t ui32Port, uint8_t ui8Pin) ,指向地址ROM_GPIOTABLE[4]处

看到这里是一个基址寻址,ROM_APITABLE是一个uint32_t型指针,指向地址 0x01000010,这样可以把它看做一个uint32_t数组
ROM_GPIOTABLE是(uint32_t )(ROM_APITABLE[4]),即取ROM_APITABLE数组的第4个元素(地址为0x01000010+44)的值,然后用一个unt32_t型指针指向这个值。(ROM_APITABLE数组存储的应当也是地址值)

TM4C123-TivaWare中函数名与函数指针在ROM中的映射相关推荐

  1. 7/7 第7篇 函数名与函数指针

    第7篇 函数名与函数指针 一 通常的函数调用 一个通常的函数调用的例子: //自行包含头文件 void MyFun(int x);    //此处的申明也可写成:void MyFun( int ); ...

  2. C语言基础(三):函数名、函数指针、指针函数的理解

    函数指针 如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址.而且函数名表示的就是这个地址.既然是地址我们就可以定义一个指针变量来存 ...

  3. C语言函数名与函数指针详解

     二.通常的函数调用一个通常的函数调用的例子: /* 自行包含头文件 */ void MyFun(int x); /* 此处的声明也可写成:void MyFun(int) */ int main( ...

  4. 彻底搞定C指针-函数名与函数指针[转]

    一 通常的函数调用     一个通常的函数调用的例子: //自行包含头文件 void MyFun(int x); //此处的申明也可写成:void MyFun( int );int main(int ...

  5. c语言函数名本质是指针,C语言的本质(12)——指针与函数

    往往,我们一提到指针函数和函数指针的时候,就有很多人弄不懂.下面详细为大家介绍C语言中指针函数和函数指针. 1.指针函数 当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需 ...

  6. python中的lambda函数用法--无需定义函数名的函数或子程序,避免代码充斥着大量单行函数

    匿名函数lambda:是指一类无需定义标识符(函数名)的函数或子程序. lambda 函数可以接收任意多个参数 (包括可选参数) 并且返回单个表达式的值. 要点: lambda 函数不能包含命令 包含 ...

  7. linux c变量命名规则,C语言中变量名及函数名的命名规则与驼峰命名法

    在程序设计中,变量名.函数名.数组名等统称为标识 符.简单地说,标识符就是一个名字.除库函数的函数名由系统定义外,其余都由用户自定义.C语言规定,标识符只能由字母(a-z,A-Z).数字 (0-9). ...

  8. c语言中函数名可不可以由用户命名,C语言中变量名及函数名的命名规则与驼峰命名法...

    在程序设计中,变量名.函数名.数组名等统称为标识 符.简单地说,标识符就是一个名字.除库函数的函数名由系统定义外,其余都由用户自定义.C语言规定,标识符只能由字母(a-z,A-Z).数字 (0-9). ...

  9. c语言驼峰命名法作用,C语言中变量名及函数名的命名规则与驼峰命名法

    在程序设计中,变量名.函数名.数组名等统称为标识 符.简单地说,标识符就是一个名字.除库函数的函数名由系统定义外,其余都由用户自定义.C语言规定,标识符只能由字母(a-z,A-Z).数字 (0-9). ...

最新文章

  1. QT删除QWidget或QLayout下的控件
  2. 动态规划之等差递减区间个数
  3. dropout与lstm的结合使用
  4. ELK三件套安装实践之路(1)
  5. Pod详解-端口设置
  6. CentOS 7.3镜像挂载搭建本地yum源
  7. RabbitMQ笔记-使用rabbitmq-c实现Fair dispatch(公平分发)
  8. Python 爬虫学习2
  9. LINUX 下 配置MySQL数据库集群
  10. js 内置对象的方法
  11. PHP如何有效实现多视频同时上传功能
  12. python文本分割_python实现大文本文件分割
  13. PHP函数array_intersect_ukey
  14. mysql软件可行性分析报告_软件工程作业 图书馆管理系统可行性分析报告
  15. java获取世界各国地址,获取世界各国、全国省份、城市、县
  16. MATLAB中fig文件多重图片数据读取
  17. 用python自动制作ppt第二讲——插入文字的两种方法和追加文字
  18. CFBI中国金融科技与区块链创新峰会2017年度盛会
  19. java开发微信第三方平台 模板消息发送消息案例
  20. algorithm——并查集

热门文章

  1. 6000php相当于,jquery – Javascript中的PMT
  2. 云计算的五个基本特征、三种服务模式、四种部署模型
  3. DDR3L和LPDDR3区别
  4. 硬件工程师必须掌握的测试工具----示波器
  5. 通过cookie跳过验证码登录
  6. python3 word转pdf
  7. 榆木搜官网_网路已为您准备好,榆木
  8. baresip 729(G.729)编码实现
  9. 互联网思维到底是什么
  10. 【华为云技术分享】根因分析