以前不怎么接触内联函数,现在在学linux内核分析,遇到了许多内联函数的使用,一直都很模糊地东西。所以今天就查阅了维基百科,才知道原来是这么回事……
内联函数有时也叫在线函数或者编译时展开函数 ,它名字是叫函数没错,好像就是一种函数但事实上它是一种编程语言结构,也就是说从源代码层面来说具有函数结构,但在编译之后却不具备函数的性质。在编译内联函数时,类似于宏替换,使用函数体替换调用处的函数名。一般在代码中会用inline这样的关键字来标注内联函数,但实际上能否形成内联函数呢,这要看编译器对该函数定义的具体处理了。
使用内联函数的目的其实是为了消除函数调用时的时间开销,常用于执行频繁的函数中。
在使用内联函数时,用来建议编译器对一些特殊函数做内联扩展用的,它建议编译器将指定的函数插入并且取代每一处调用该函数的地方。这样做能节省每次调用函数带来的额外时间花销。但是编译器在选择是否要使用内联函数时要权衡程序的占用空间和执行效率再决定,因为过多的较复杂的函数进行内联扩展会带来很大的存储资源开支,另外还要特别注意的是在对递归函数做内联扩展时可能会带来部分编译器的无穷编译。
通常,在C语言中中,内联函数展开由使用带参宏(Macros)在源码级完成。内联提供了几个更好的方法:
- 宏调用并不执行类型检查,甚至连正常参数也不检查,但是函数调用却要检查。
- C语言的宏使用的是文本替换,可能导致无法预料的后果,因为需要重新计算参数和操作顺序。
- 在宏中的编译错误很难发现,因为它们引用的是扩展的代码,而不是程序员键入的。
- 许多结构体使用宏或者使用不同的语法来表达很难理解。内联函数使用与普通函数相同的语言,可以随意的内联和不内联。
- 内联代码的调试信息通常比扩展的宏代码更有用。
使用内联函数也有不足之处:
事实上编译器比程序设计者更清楚对于一个特定函数是否适合进行内联扩展,某些情况下或许程序设计者觉得要使用内联函数,而编译器则可能更倾向于不适用内联,甚至根本不能完成内联;
尽管内联函数或者非内联函数的转换易于宏的转换,但同时它因此而增加的维护开支会使得它的优点更不突出;
对基于C的编译系统,内联函数的使用可能会大大增加编译时间,因为每个调用该函数的地方都需要替换成函数体,代码量的增加带来了潜在的编译时间的增加。
要注意,内联函数的生命必须要和函数体放在一起才会有效,像inline func(int var);这样的声明是没有效果的,编译器智慧把它当做普通函数对待;应该是这样才有效:
inline int func(int var)
{
//函数体内容
}
可以把它作为一般函数那样调用,但事实上它的执行速度的确比一般函数要快。
后面会接着用实例再说名有关内联函数的知识点。