前言
在计算机科学中,内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展(有时称作在线扩展);也就是说建议编译器将指定的函数体插入并取代每一处调用该函数的地方(上下文),从而节省了每次调用函数带来的额外时间开支。但在选择使用内联函数时,必须在程序占用空间和程序执行效率之间进行权衡,因为过多的比较复杂的函数进行内联扩展将带来很大的存储资源开支。另外还需要特别注意的是对递归函数的内联扩展可能引起部分编译器的无穷编译。
内联扩展是一种特别的用于消除调用函数时所造成的固有的时间消耗方法。一般用于能够快速执行的函数,因为在这种情况下函数调用的时间消耗显得更为突出。这种方法对于很小的函数也有空间上的益处,并且它也使得一些其他的优化成为可能。
通常,在C语言中,内联展开的功能可由带参宏(Macros)在源码级实现。内联提供了几个更好的方法:
1,宏调用并不执行类型检查,甚至连正常参数也不检查,但是函数调用却要检查。
2,C语言的宏使用的是文本替换,可能导致无法预料的后果,因为需要重新计算参数和操作顺序。
3,在宏中的编译错误很难发现,因为它们引用的是扩展的代码,而不是程序员键入的。
许多结构体使用宏或者使用不同的语法来表达很难理解。内联函数使用与普通函数相同的语言,可以随意的内联和不内联。
4,内联代码的调试信息通常比扩展的宏代码更有用。
对于基于C的编译系统,内联函数的使用可能大大增加编译时间,因为每个调用该函数的地方都需要替换成函数体,代码量的增加也同时带来了潜在的编译时间的增加。
本节我们将基于“STM32 进阶教程 3 - 软件实现高精度延时 1”内能来介绍内联函数的命定义与使用,以及其带来的差别。
示例详解
基于硬件平台: STM32F10C8T6最小系统板, MCU 的型号是 STM32F103c8t6, 使用stm32cubemx 工具自动产生的配置工程,使用KEIL5编译代码。
本示例所用的最小系统板原理图:
-
- 关于CUBEMX工具及KEIL工具的操作将不再细讲,如果还有不熟悉的可以查看之前的教程文档。下面直接介绍工程配置:
-
-
- 系统时钟树
-
-
- 定时器配置
-
-
- 引脚配置
-
-
- 中断配置(保持默认)
-
-
工程代码
- 将事先准备好的delay.c和delay.h文件加到工程中,
Delay.h文件放在INC文件夹下即可。
-
-
- 在main.c 中加入如下图所示代码:
-
- 编译工程,下载程序看效果:PC13引脚产生周期为100us 占空比为50%的方波信号,同时可以看到LED是常的,通过逻辑分析仪工具,可以看到PC13引脚上的波形:
编译后的代码大小:
对应的汇编代码:
接下来我们在delay_us函数实现前加上inline 关键字(也可以是 __inline 或 __INLINE)再次编译。
执行效果和代码大小均不变:
仿真查看其汇编代码:
发现并没有像宏一将展开,其实现还是一样,并没有实现内联展开,这里因为 inline只适合涵数体内代码简单的函数数使用,不能包含复杂的结构控制语句例如while、switch,并且内联函数本身不能是直接递归函数(自己内部还调用自己的函数)。
同时在keil的帮助文档中不有如下说明
接下来我们在main.c的USER CODE BEGIN 0区加入如下代码:
在USER CODE BEGIN 3中加入如下代码:
重新编译,仿真,查看对应汇编代码,发现其已经实现了内联,g函数中的f(x),与 f(y)对应的源码直接在g函数中:
通过上面的实例,我们已基本学会基于keil MDK平台的stm32 中内联函数的使用,了解决了其使用的基本方法(更多关于inline的说明可以查看对应的帮助文档):
OK,本期实验完成!下期见!同时如果大家有什么疑问或是有想了解的其它内容,也欢迎大家留言!!最后喜欢这个公众号的同学们记得加关注了,会有不定期技术干货推出!!
文中源码资料下载,在公众号里给十三发消息:
下载|STM32进阶教程5
关注十三公众号