目录
一、什么是内联函数
内联关键字是inline,用于修饰函数,内联函数的实现需要用inline关键字修饰,内联函数的函数声明不需要加inline关键字,只在函数的声明加修饰,不生效。
二、内联函数和宏区别
1、宏定义
函数宏的本质:在编译器在对源码的预处理阶段,无脑进行宏符号替换,替换时不做语法检查,比如"入参"类型是否匹配,"入参"个数是否匹配等。
2、内联函数
内联函数的本质:inline关键字会告诉编译器,此函数是内联函数,希望编译器尽可能的在编译阶段将此函数展开到调用此函数的地方,且对此内联函数按照常规函数一样进行语法检查,比如入参类型,入参个数等。
3、内联和宏对比
1)、语法检查差别
2)、处理阶段
对源码进行预处理,预处理命令:gcc -E main.c -o main.i , 生成mian.i文件。
查看main.i内容,可以发现宏替换在预处理阶段已经完成,内联函数在预处理阶段无任何变化
内联函数会被语法检查,所以内联函数编译阶段被处理。
三、内联函数和普通函数
1、普通函数调用过程
如下图所示,在main函数中调用普通函数test_func(),图左是C源码,图右是编译生成的汇编语言
我们梳理上图图右汇编流程发现:
1)、在mian函数中调用了test_func()函数,汇编语句为:bl test_func 。
2)、test_func()函数刚开始执行,就执行了push语句,将R7(通用寄存器之一)和LR(函数返回地址寄存器)寄存器的值压入栈中。
3)、而后执行函数逻辑。
4)、在test_func()函数的末尾,执行了pop语句,将栈中数据弹出到R7和PC寄存器中,然后返回到main函数中继续执行。
2、内联函数调用过程
内联函数相比宏函数 处理阶段是在编译阶段(语法检查)后进行替换,其他效果与宏函数相同,这里为了方便展示,我们直接使用宏函数进行实验。
如下图所示,在main函数中调用宏函数test_func,图左是C源码,图右是编译生成的汇编语言
可见,在main函数中未进行bl(函数调用),而是直接执行printf操作。
3、普通函数和内联函数对比
1)、普通函数在调用过程中,会对寄存器中内容进行上下文切换(push和pop操作),而内联函数则不需要,所以普通函数相比内联函数,耗时要多一些。
2)、当函数使用次数比较多的时候,内联函数在每个调用的地方都会被展开,所以导致固件大小会变大,同一段代码会多次重复出现在固件中。而普通函数则没有此问题,不管调用的函数的次数多少,函数在固件中均只占用一处,空间利用率较高。
四、总结
1、内联函数相比宏函数,会进行语法检查。宏函数是在预处理阶段生效,内联函数是在编译阶段进行语法检查然后替换。
2、内联函数相比普通函数,少了上下文切换的步骤所以执行会更快一些。
3、内联函数被多次调用,会使固件大小膨胀,内联函数的高速是以空间来换时间。
4、内联函数不可递归。
5、如果函数内容太过于复杂,编译器会忽略inline关键字,把他当成普通函数来处理。