它看起来非常奇怪,但我无法编译以下简单代码:
inline void inline_func() {}
static inline void static_inline_func() {}
void some_func()
{
// THERE IS A PROBLEM with "inline" function
inline_func();
// THERE IS NO PROBLEM with "static incline" function
static_inline_func();
}
int main(int argc, char *argv[])
{
some_func();
return 0;
}
编译器只是产生错误:
$ gcc -Wall -o main main.c
/usr/bin/ld: /tmp/ccs7lKMm.o: in function `some_func':
main.c:(.text+0x15): undefined reference to `inline_func'
collect2: error: ld returned 1 exit status
我也用 Clang 编译器尝试了这段代码,并遇到了类似的问题。
UPD。 请不要将此问题视为重复问题而关闭。 这不是关于
inline
和 static inline
之间差异的问题。
这个问题是关于为什么某些编译器无法编译内联函数而其他编译器可以编译内联函数的原因(请参阅评论)。
为什么有些编译器无法编译内联函数
内联是神奇的。内联(没有
extern
或 static
)意味着该函数有 two 定义 - 一个是您提供的内联定义,另一个是同一函数的其他外部定义。编译器可以自由选择任一函数 - 它的内联或外部版本。
您发布的内联函数代码无法被某些编译器编译,因为某些编译器选择使用函数的外部定义。你没有提供它。 您的代码无效。您必须提供函数的外部定义,例如通过编译单独的文件 并与之链接
因为今天的编译器与 30 年前相比快得离谱,所以单独的
inline
没有多大意义。使用static
。
这是完全正常且正确的行为。请参阅 没有“static”或“extern”的“内联”在 C99 中有用吗?,了解如果将函数定义为
inline
会发生什么情况。
粗略地说,您已经告诉编译器if它希望内联函数
inline_func()
,您已经向它提供了执行此操作的代码。此定义仅用于内联,并且本身不会导致发出函数的独立副本(或 C 标准语言中的“外部定义”)。
并且编译器不需要实际内联调用它的函数;它可能会发出一条调用指令。如果是这样,那么程序中的某个地方必须有该函数的独立副本。
gcc 和 clang 在不进行优化的情况下进行编译时,永远不会内联函数调用(除非使用不可移植的
always_inline
属性 进行声明)。相反,它尝试发出对独立函数的调用,如上所述,该函数在您的程序中不存在。如果启用优化(-O
),您会发现程序编译和链接成功。 (尽管在其他情况下,即使启用了优化,编译器仍然可能选择不内联某些函数,如果它认为这不是整体性能提升的话。)
C 标准允许这两种行为。 C17 6.7.4p7 说“未指定是否调用该函数 使用内联定义或外部定义。”
为了让程序可靠地工作,您可以添加以下行
extern inline void inline_func(void);
它告诉编译器使用上面给出的普通
inline
相同的定义来发出该函数的独立副本。那么即使编译器选择不内联函数调用,也会存在一个可以成功调用的独立副本。 尝试一下神箭。