我在.c文件中定义了我的函数(没有头文件声明),如下:
inline int func(int i) {
return i+1;
}
然后在同一个文件中我在下面使用它:
...
i = func(i);
在链接期间,我收到了“undefined reference to 'func'”的错误。为什么?
C99标准中的inline
模型与大多数人想象的有些不同,特别是与C++中使用的不同。
inline
只是一种提示,使编译器不会抱怨有重复定义的符号。它不能保证函数被内联,也不能确保需要时实际生成符号。要强制生成符号,您需要在inline
定义之后添加某种实例化方式:
int func(int i);
通常情况下,您应该在头文件中定义inline
,然后将其包含在多个.c文件(编译单元)中。并且在这些编译单元中只有一处会用到上述行。您可能看到的问题只是因为您没有对编译器进行优化运行。因此,在.c文件中使用inline
并没有太多意义,最好使用static
代替,即使额外使用inline
也不会带来太大好处。
inline
的 extern
文件作用域声明确实会强制定义不是内联的。 - Christophinline
函数。 - Jens Gustedtecho "int f(void); inline int f(void){return 42;}" | cc -x c -Wall -Wextra -Wpedantic -pedantic-errors -Werror -O3 -std=c99 -S - -o -
。这是标准的扩展(还是gcc的误解)? - alx - recommends codidactC99的内联语义经常被误解。 inline
修饰符有两个作用:
首先,对于static inline
和extern inline
声明,它作为编译器提示。如果删除修饰符,则语义保持不变。
其次,在没有static
或extern
的情况下,提供内联定义作为外部定义的替代方案,外部定义必须存在于另一个翻译单元中。不提供外部定义将导致未定义行为,通常表现为链接失败。
如果您想将函数放入共享库中,但同时也要使函数体可用于优化(例如内联或专业化),这是特别有用的。假设编译器足够智能,这允许您恢复 C++ 模板的许多好处,而无需通过预处理程序来实现。
请注意,具体情况比我在此处描述的要复杂一些,因为拥有另一个文件范围的非内联外部声明将触发 Jens' 答案中所述的第一种情况,即使定义本身是 inline
而不是 extern inline
。这是有意设计的,以便您可以在头文件中拥有单个内联定义,通过添加单个外部声明行将其包含到提供外部定义的源文件中。
static inline int func(int i) {
return i+1;
}
...
i = func(i);
inline
在C和C++中的含义是不同的。 - Peter Cordesstatic
和 inline
是不相关的。也就是说,static
意味着它必须存在,而 inline
(根据定义)则不需要。(所谓“不存在”,是指作为一个定义的符号,因为它将被内联)。 - sherrellbc
static
,要么提供一个非内联定义,以便链接器可以找到它。 - Daniel Fischer