我没有回答“它有什么作用?”,而是回答“我如何让它做我想做的事?”有 5 种内联,在 GNU C89、标准 C99 和 C++ 中都可用。 MSVC 有 一些 (注意我没有测试 MSVC 代码)
总是内联,除非地址被占用
将__attribute__((always_inline)) 添加到任何声明中,然后使用其中一个
以下情况以处理其地址被占用的可能性。
你可能永远不应该使用它,除非你需要它的语义(例如,以某种方式影响程序集,或者使用alloca)。编译器通常比你更清楚它是否值得。
MSVC 的 __forceinline 看起来基本相同,但显然它拒绝在其他编译器管理得很好的很多常见情况下(例如,当优化关闭时)内联。
内联并发出一个弱符号(如 C++,又名“让它工作")
__attribute__((weak))
void foo(void);
inline void foo(void) { ... }
请注意,这会留下一堆相同代码的副本,并且链接器会任意选择一个。
MSVC 在 C 模式下似乎没有完全相同的功能,尽管有一些类似的东西。 __declspec(selectany) 似乎只在谈论数据,所以可能不适用于函数?还有对weak aliases 的链接器支持,但这在这里有效吗?
内联,但从不发出任何符号(留下外部引用)
__attribute__((gnu_inline))
extern inline void foo(void) { ... }
MSVC 的 __declspec(dllimport) 结合实际定义(否则不寻常),据说是这样做的。
emit always(对于一个 TU,解决前面的问题)
提示版本在 C++ 中发出一个弱符号,但在 C 的任一方言中发出一个强符号:
void foo(void);
inline void foo(void) { ... }
或者您也可以不使用提示,这两种语言都会发出强烈的符号:
void foo(void) { ... }
通常,您在提供定义时就知道您的 TU 是什么语言,并且可能不需要太多内联。
MSVC 的 __declspec(dllexport) 应该是这样做的。
在每个 TU 中内联和发射
static inline void foo(void) { ... }
对于除static 之外的所有这些,您可以在上面添加void foo(void) 声明。这有助于编写干净的标头的“最佳实践”,然后#include使用内联定义创建一个单独的文件。然后,如果使用 C 风格的内联,#define 在一个专用 TU 中使用不同的宏来提供外联定义。
如果标头可能同时用于 C 和 C++,请不要忘记 extern "C"!
还有一些相关的事情:
从不内联
将__attribute__((noinline)) 添加到函数的任何声明中。
MSVC 有 __declspec(noinline) 但它被记录为仅适用于成员函数。但是,我看到提到可能会阻止内联的“安全属性”?
如果可能,强制将其他函数内联到这个函数中。
将__attribute__((flatten)) 添加到函数的任何声明中。
请注意,noinline 比这更强大,其定义在编译时未知的函数也是如此。
MSVC 似乎没有等效项。我见过一次提到[[msvc::forceinline_calls]](应用于语句或块),但它不是递归的。