• 2008-11-09

    zt令人困惑的inline,extern inline,staitc inline

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://dionysus.blogbus.com/logs/31152920.html

     轉載自:http://goldencz.spaces.live.com/blog/cns!BDF1ADF5C4D1F962!343.entry

    令人困惑的inline,extern inline,staitc inline

    近日在一个头文件中使用inline来定义了一个需要高效率的函数,被告知在头文件中定义函数看起来不好,于是挪至C文件中重新定义,只在头文件中保留了声明。需要说明的是,该函数在其他几个文件中有使用,使用vc的编译器。
    编译:通过!
    链接:被告知有几个函数无法找到,这几个函数恰好就是我定义的inline函数
     
    百思不得其解,于是询问旁人,被告知:这是microsoft编译器的问题,使用GCC则不会出现该问题。测试之,果然如此。又有建议称,在inline前面加extern可解决该问题,果然,编译链接通过。
     
    问题解决了,不过这个问题实在让我困惑,究竟是什么原因造成这个问题呢?使用google深入调查了一番,找到一个有关inline的网页(http://www.greenend.org.uk/rjk/2003/03/inline.html)并结合其他资料,得出如下结论:
    1. inline并不是在所有地方都会inline(这个是早就知道的,例如递归不能展开,使用了函数名作为地址也不能展开)
    2. C标准对于何时该inline,何时不inline定义的很模糊,造成了不同编译器在实现inline功能时存在较大差异。
    3. 如果在c文件中定义一个inline函数,那么编译器实际上一定会产生一份该函数的汇编代码(object code),该函数会在这个文件中任何一处调用中被展开(inline),并且整个程序中不能存在其他相同名字的函数。如果你想在别的文件中使用这个函 数,那么可以将该函数的一个声明放到头文件中,但是,请注意:其他使用这个函数的文件中,该函数不被展开,而被作为一个普通的函数调用!!!
    4. 如果inline 和extern 一起使用,则不会产生任何object code,其效果几乎和宏一样。那就意味着,这个函数的名字并没有进入符号表。
    这会导致两个问题:第一,如果你使用该函数名作为一个指针,则会发生找不到符号的现象。第二,同样名字的函数,可以重复出现而编译器不会报错。
    5. 如果inline 和static 一起使用,则是否产生object code将取决于这个函数如何使用。如果不存在对该函数地址的应用,且理论上是可以展开的,则不会生成object code。否则将产生object code,其影响从4可得知。
     
    以上3-6的结论是GNU c的解释,c99标准中稍有不同
    1. 声明和定义中都有inline,并且没有extern,则不会产生object code。它必须在同一个翻译单元(translate unit)中存在一个定义。如果你在另一个文件中定义了同名的函数,则编译器可以选择使用哪个函数,但是,编译器必须在文档中声明如何选择。
    2. 某个函数的(任何)一个声明中有inline,但是其他的声明中没有inline或者extern,那么会产生object code。在同一个翻译单元(translate unit)中必须存在一个该函数的定义。那么其他翻译单元中对该函数的应用将作为一个普通的函数调用。
    3. staitc inline 同时使用,则可能会也可能不会产生object code,这要看对该函数的使用情况而定。这点与GNU相同。

    收藏到:Del.icio.us