C,内联函数和GCC

xde*_*000 8 c

如果我有:

inline int foo(void)
{
   return  10 + 3;
}

int main(void)
{
   foo();
}
Run Code Online (Sandbox Code Playgroud)

使用GCC,文件编译得很好,但链接器返回 undefined reference to foo

相反,如果我删除inline链接器很高兴!

看起来链接器可以看到外部定义的标识符,但内联定义的标识符不是.

此外,如果我使用-O3标志编译,链接器将看到内联定义的标识符.

有什么问题?

Mar*_*rio 6

好的,所以在阅读了VivienG的链接之后,我想我已经理解了这个错误信息背后的确切原因.它令人困惑和误导(至少对我来说;如果你只有一个翻译单元就不会发生这种情况),但有可能解释:

  • 假设编译器不想实际内联代码,它必须知道放置该函数的位置,特别是当它在多个转换单元中使用时.

  • 经典的方法是创建多个副本,每个翻译单元一个(或至少对于那些使用它的单位).

  • 这可能会导致问题,例如在尝试进行某些函数指针比较时(尽管如此,仍然会留下问题).

为了解决这个问题(以及我可能没有在这里列出的其他问题),他们认为其中一些实际上非常整洁(尽管 - 如我所说 - 在我看来是误导性的)解决方案:

您可以inline按照您所知的方式声明函数,但同时告诉编译器将非内联版本放在哪里使用extern关键字.

因此,在您的示例中,您将按原样保留函数并将其放在头文件中(因此可以知道它将在何处使用):

inline int foo(void)
{
     return  10 + 3;
}
Run Code Online (Sandbox Code Playgroud)

另外,要告诉编译器在哪里放置非内联版本,您必须在一个翻译单元中再添加一个"前向"声明:

extern inline int foo(void);
Run Code Online (Sandbox Code Playgroud)

因此,与经典函数相比,整个概念基本上是相反的:将实现放在标题中,然后在一个文件中进行简短声明.

如前所述,在使用-O3参数时,标记的所有代码inline实际上都是内联的,这不会导致问题发生.