如何从另一个翻译单元内联函数?

How do I inline a function from another translation unit?

考虑下面的两个翻译单元。我的目标是在 file1.cmain.c.

中内联函数 add

file1.c:

extern inline int add(int x, int y)
{
 return x + y;
}

void g(void)
{
  add(1, 1);     // this will probably be inlined
}

main.c:

extern int add(int, int);

void f(void)
{
  add(2, 4);    // this doesn't appear to be inlined
}

int main(void)
{
  f();
  return 0;
}

生成的程序集表明 add(2, 4) 未内联。为什么?或者规则是,对于要在翻译单元中内联的函数,它 必须 在翻译单元中声明为内联,因此它的定义 必须 被人看见?

传统上,编译器单独处理每个翻译单元,因此对每个翻译单元分别执行函数内联等优化。在这样的设置中,无法内联对不同翻译单元的函数调用。

然而,大多数现代编译器都有一个称为“全程序优化”或“Link 时间优化”的功能,即使两个函数位于不同的位置,它也能够执行 interprocedural optimization(包括内联)翻译单位。但在某些编译器中,此功能默认情况下是禁用的,必须在 compiler/linker 选项中显式激活。

inline 关键字仅向编译器提供提示,建议内联函数。它是否实际内联由编译器的优化器决定。许多编译器忽略提示并根据函数的大小和调用频率自行判断函数是否应该内联。

但是,如果编译器优化被激活,大多数编译器只会执行函数内联。如果不是,那么即使声明为内联的函数也不太可能被内联。

My goal is to inline the function add both in file1.c and main.c

为了实现这个目标,我建议你要么

  • 激活上述编译器的整个程序Optimization/Link时间优化功能,希望编译器的优化器自动内联适当的函数,或者

  • 在两个翻译单元中定义函数,但将其设为static inline,或

  • 在正好一个翻译单元中将函数定义为extern inline(为了不违反one definition rule), and simply as inline (without any 'extern' or 'static' modifier keywords) in all other translation units, making these so-called "inline definitions" pursuant to §6.7.4 ¶7 of the C11 standard,这由编译器决定是否采用外部定义或同一翻译单元中的定义。

如果您在所有翻译单元中使用 static inline,那么您 运行 在可执行文件中存在不必要的代码重复的风险。在所有函数调用都被编译器优化器内联的情况下,这种代码重复无论如何都会发生,所以在那种情况下它无关紧要。但是,在编译器决定不内联函数的情况下,编译器将为每个翻译单元生成一个函数,从而在可执行文件中复制代码。这可以通过在一个文件翻译单元中使用 extern inline 并在所有其他翻译单元中简单地使用 inline(参见上面描述的“内联定义”)来避免。

但是,声明为 extern inline 或简单地 inline(不是 static inline)的函数有一个缺点,根据 §6.7.4 ¶3 of the C11 standard,它们不能使用任何变量内部链接,只有有外部链接或没有链接的变量(如局部自动变量或有外部链接的全局变量)。此外,它们可能不会调用任何具有内部链接的函数(具有关键字 static 的函数),只能调用具有外部链接的函数。

由于提到的使用 static inlineextern inlineinline 的缺点,我建议您根本不要使用它们。相反,我建议您只需确保正确设置编译器和链接器(见上文)上的适当优化设置,并让这两个程序自行决定应内联哪些函数。

请注意,此答案仅适用于 C 语言,不适用于 C++,因为您用“C”标记了问题。 inline keyword in C++ has a slightly different meaning and you can use extern inline in all translation units without violating the C++ one definition rule.