大家都知道它会快, 但我想说一点我之前不知道的: 如果希望inline有效果, 使用的地方就得与定义的地方在同一个文件, 得知道函数体. 我觉得原因是这样的: 如果不在一个文件, 那么调用它的函数就必然会是call了, call的话, 就不会省去任何函数的开销. 我们知道, c是单文件编译的(局限我的所知), 它看不到其它文件. 反过来, 如果函数体与调用在同一个文件中, 那么就可以把这个函数拷贝过去, 然后再来编译.
因此如果是多文件都需要使用, 典型做法是在一个头文件中实现(是的, 与一般的头文件不包括实现的规则不同, 这是个例外), 然后声明为static(否则有重定义问题). 当然也是有代价的:
编译得到的文件变大了些;函数没有地址, 没法用函数指针, debugger也用不了;当然你可能发现第2点说的不对, 如果用函数指针, 编译器也没有报错, 那是因为编译器看到用了函数指针, 放弃了优化. inline只是建议, 不一定真的优化.
inline这个关键词,是从C99开始出现的。它要解决的问题很明确,对于那些短小精干频繁调用的函数,如果是inline的,编译的时候,函数调用位置会被替换成函数的代码块,省掉了函数调用的压栈出栈等操作,可以加快程序的执行速度,代价只是增加了一点点程序文件的体积。本文以gcc的inline行为为准。
1, static inline
这是最纯粹的inline用法,我们始终要记住,C语言的编译是按文件进行的,每个.c文件单独编译,最后链接在一起。既然是单独编译,要发挥inline的作用,定义为inline的函数,必然要与调用者在同一个文件中。static inline的语义,就是先static,此函数只在当前文件可见,然后inline,在调用处展开。
另外,inline要出现在函数定义(definition)的地方,出现在申明(declaration)的地方没有意义!如果一个函数是static inline,就直接定义了,没有必要再申明,在申明的位置出现inline反而可能会有编译错误。
inline对于编译器而言,只是个建议,不是强制,如下两种情况,编译器会忽略掉inline:
(1)函数的地址被使用的时候。如通过函数指针对函数进行了间接调用。这种情况下就不得不为static inline函数生成独立的汇编码,否则它没有自己的地址。
(2)其他一些无法展开的情况,比如函数本身有递归调用自身的行为等。
其实,对于以上两种情况,程序员就不应该使用inline。
2, inline
对于gcc而言,仅有inline的函数(无static),在当前文件内部,其表现与static inline一样,在调用处展开,而对于外部文件的调用(没有static修饰,就是extern函数),跟普通全局函数一样。因此,gcc实际上在只有inline的时候,一定会为函数生成一份独立的汇编码,以便被别的模块调用。在别的文件中,这个函数跟其它全局函数没有区别。
3, extern inline
这是不建议使用的定义方式,gcc一定不会为这样定义的函数生成独立的汇编码。
4, inline与gcc -On优化参数
inline关键字仅仅是建议编译器做内联展开处理,而不是强制。在gcc编译器中,如果编译优化设置为-O0,即使是inline函数也不会被内联展开,除非设置了强制内联(__attribute__((always_in line)))属性。
如果使用 -O0,函数定义为 inline,会有链接错误。 -O0表示inline函数不展开,还是调用,inline表示对当前文件的调用不生成独立的汇编码,因此在链接的时候,会有找不到inline函数的错误。
最后,我个人的一点感觉(不确定):使用-O3的时候,static的函数,gcc也可能自动为其加上inline属性。