我没有回答“它有什么作用?”,而是回答“我如何让它做我想做的事?” 有 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)
似乎只在谈论数据,所以可能不适用于函数?还有对弱别名的链接器支持,但这在这里有效吗?
内联,但从不发出任何符号(留下外部引用)
__attribute__((gnu_inline))
extern inline void foo(void) { ... }
MSVC__declspec(dllimport)
与实际定义(否则不寻常)相结合,据说可以做到这一点。
总是发出(对于一个 TU,解决前面的问题)
暗示的版本在 C++ 中发出一个弱符号,但在 C 的任一方言中发出一个强符号:
void foo(void);
inline void foo(void) { ... }
或者您可以在没有提示的情况下执行此操作,这会在两种语言中发出一个强符号:
void foo(void) { ... }
通常,当您提供定义时,您知道您的 TU 是什么语言,并且可能不需要太多内联。
__declspec(dllexport)
据说MSVC 就是这样做的。
在每个 TU 中内联和发射
static inline void foo(void) { ... }
对于除此之外的所有这些static
,您可以在上面添加一个void foo(void)
声明。这有助于编写干净的标头的“最佳实践”,然后#include
使用内联定义创建一个单独的文件。然后,如果使用 C 风格的内联,则#define
在一个专用 TU 中使用不同的宏来提供外联定义。
不要忘记extern "C"
是否可以从 C 和 C++ 中使用标头!
还有一些相关的事情:
从不内联
添加__attribute__((noinline))
到函数的任何声明。
MSVC 有__declspec(noinline)
,但它被记录为仅适用于成员函数。但是,我已经看到提到可能阻止内联的“安全属性”?
如果可能,强制将其他函数内联到这个函数中。
添加__attribute__((flatten))
到函数的任何声明。
请注意,noinline
它比这更强大,其定义在编译时未知的函数也是如此。
MSVC 似乎没有等价物。我见过一次提到[[msvc::forceinline_calls]]
(应用于语句或块),但它不是递归的。