use*_*390 7 c inline declaration function linkage
考虑下面的两个翻译单元。我的目标是内联函数addinfile1.c和main.c.
文件1.c:
extern inline int add(int x, int y)
{
return x + y;
}
void g(void)
{
add(1, 1); // this will probably be inlined
}
Run Code Online (Sandbox Code Playgroud)
主文件:
extern int add(int, int);
void f(void)
{
add(2, 4); // this doesn't appear to be inlined
}
int main(void)
{
f();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
生成的程序集表明 add(2, 4) 未内联。为什么?或者是它的规则,对于在翻译单元内联函数,因此它必须被内嵌在翻译单元中声明,因此其定义必须被视为?
传统上,编译器分别处理每个翻译单元,因此对每个翻译单元分别执行函数内联等优化。在这样的设置中,不可能内联对不同翻译单元的函数调用。
但是,大多数现代编译器都有一个称为“整个程序优化”或“链接时间优化”的功能,即使两个函数驻留在不同的翻译单元中,它也能够执行过程间优化(包括内联)。但在某些编译器中,此功能默认禁用,必须在编译器/链接器选项中显式激活。
的内联的关键字只是提供一个提示给编译器表明的函数被内联。是否实际内联由编译器的优化器决定。许多编译器会忽略提示并根据函数的大小和调用频率自行判断是否应该内联函数。
但是,如果激活了编译器优化,大多数编译器只会执行函数内联。如果不是,那么即使声明为 inline 的函数也不太可能被内联。
我的目标是在 file1.c 和 main.c 中内联函数 add
为了实现这一目标,我建议您要么
激活上述编译器的整体程序优化/链接时间优化功能,并希望编译器的优化器自动内联适当的函数,或
在两个翻译单元中定义函数,但 make it static inline,或
将函数定义为extern inline恰好在一个翻译单元中(为了不违反一个定义规则),并inline在所有其他翻译单元中简单地定义为(没有任何 'extern' 或 'static' 修饰关键字),使这些所谓的“内联”定义”符合 C11 标准的 §6.7.4 ¶7,这让编译器决定是否采用外部定义或同一翻译单元中的定义。
如果您static inline在所有翻译单元中使用,那么您将面临在可执行文件中出现不必要的代码重复的风险。在编译器优化器内联所有函数调用的情况下,无论如何都会发生这种代码重复,因此在这种情况下无关紧要。但是,在编译器决定不内联函数的情况下,编译器将为每个翻译单元生成一个函数,复制可执行文件中的代码。这可能可以通过extern inline在一个文件翻译单元中使用并inline在所有其他翻译单元中简单地(参见上述“内联定义”)来防止。
但是,声明为extern inline或简单地inline(not static inline) 的函数有一个缺点,即根据C11 标准的 §6.7.4 ¶3,它们不能使用任何具有内部链接的变量,只能使用具有外部链接的变量或没有链接的变量(例如 local具有外部链接的自动变量或全局变量)。此外,它们不能调用任何具有内部链接的函数(带有关键字的static函数),只能调用具有外部链接的函数。
由于上述使用static inline,extern inline和 的缺点inline,我建议您根本不要使用它们。相反,我建议您只需确保正确设置编译器和链接器(见上文)上的适当优化设置,并让这两个程序自行决定应该内联哪些函数。
请注意,此答案仅适用于 C 语言,不适用于 C++,因为您将问题标记为“C”。inlineC++ 中的关键字的含义略有不同,您可以extern inline在所有翻译单元中使用,而不会违反C++ 一个定义规则。