inline, static inline, extern inline

08 Dec 2012 by fleuria

记得以前看过的,不过extern inline的语义全然记不起来了,还得多把东西写下来才行呢。

Inlining in GNU89

inline并非标准委员会的创作,最早给出实现的GNU89,在一段时间内暂且成为事实上的标准:

  • inline

    函数有可能会被展开,但总保留一个未展开的函数,其符号对外部可见,因此不可以将这样的函数放到头文件里,不然链接时会报重名的错误。

  • static inline

    函数可能会被展开,但总保留一个未展开的函数,这个函数在不同的编译单元中会存在多个副本,但其符号仅在当前编译单元可见。

  • extern inline

    函数可能会被展开,且不会保留一个未展开的函数,当函数没有展开时,会调用某编译单元(可以是当前编译单元)中的同名函数,也就是要求人肉在某.c文件中重复一遍。

到这里的共同点是inline都仅仅是对编译器的一个提示,到具体情景中要展开还是不展开,就要看编译器的心情了。但是如果不展开,就调那只未展开的函数作为后备措施,所以static与extern其实影响的是”备用”的那只函数,而与函数的真正展开与否无关。

But things have changed in C99

在C99中,inline第一次被标准化,不过语义与GNU89相比已经有了比较大的差异:

  • inline

    与GNU89的extern inline有点像,函数有可能会被展开,但不会保留一个未展开的函数了,需要人肉在_另一个_编译单元中提供一个同名函数。

  • extern inline

    与GNU89的inline比较像,函数有可能会被展开,但总保留一个未展开的函数,且符号对外部可见,也是只能存在于一个编译单元中。于是也不能把extern inline放到头文件里面了。

  • static inline

    同GNU89兼容。

Sample

https://gist.github.com/4238509

Conclusion

还是只用static inline吧。

Reference

  • http://stackoverflow.com/questions/216510/extern-inline
  • http://clang.llvm.org/compatibility.html#inline