我在.c(没有标头声明)中定义了我的函数,如下所示:
inline int func(int i) {
return i+1;
}
然后在下面的同一个文件中我使用它:
...
i = func(i);
在链接过程中,我得到了“未定义的'func'引用”。为什么呢?
答案 0 :(得分:42)
C99中的inline
模型与大多数人的想法略有不同,特别是与C ++使用的模型不同
inline
只是一个提示,编译器不会抱怨双重定义的符号。如果需要,它不保证函数内联,也不保证生成符号。要强制生成符号,您必须在 inline
定义之后添加一种实例化:
int func(int i);
通常,您在头文件中有inline
定义,然后包含在几个.c文件(编译单元)中。并且您只在其中一个编译单元中拥有上述行。您可能只看到了问题,因为您没有对编译器运行使用优化。
因此,在.c文件中使用inline
的用例没有多大意义,最好只使用static
,即使是额外的inline
也没有给你买得多。
答案 1 :(得分:31)
C99内联语义经常被误解。 inline
说明符有两个目的:
首先,作为static inline
和extern inline
声明的编译器提示。如果删除说明符,语义将保持不变。
其次,在原始inline
(即没有static
或extern
)的情况下,提供内联定义作为外部定义的替代,必须存在于不同的翻译单位。不提供外部行为是未定义的行为,通常表现为链接失败。
如果您希望将函数放入共享库,但是也可以使函数体可用于优化(例如内联或专门化),这将非常有用。假设一个足够智能的编译器,这使您可以恢复C ++模板的许多好处,而无需跳过预处理器箍。
请注意,它比我在这里描述的更麻烦,因为有另一个文件范围非内联外部声明将触发Jens回答中描述的第一种情况,即使定义本身是inline
而不是{ {1}}。这是设计使得你可以在头文件中有一个内联定义,你可以通过为外部声明添加一行来包含到提供外部文件的源文件中。
答案 2 :(得分:0)
这是因为GCC处理内联函数的方式。 GCC执行内联替换作为优化的一部分。
要消除此错误,请在内联之前使用static
。 static
关键字强制编译器使用static关键字强制编译器采用此内联函数,从而使程序成功编译。
static inline int func(int i) {
return i+1;
}
...
i = func(i);