62

I defined my function in .c (without header declaration) as here:

inline int func(int i) {
 return i+1;
}

Then in the same file below I use it:

...
i = func(i);

And during the linking I got "undefined reference to 'func'". Why?

4

3 回答 3

70

C99 中的inline模型与大多数人想象的有些不同,尤其是与 C++ 使用的模型不同

inline只是提示编译器不会抱怨双重定义的符号。如果需要,它不能保证函数是内联的,也不能保证生成符号。要强制生成符号,您必须在定义之后inline添加一种实例化:

int func(int i);

通常你会inline在一个头文件中有定义,然后包含在几个 .c 文件(编译单元)中。而且您只会在其中一个编译单元中拥有上述行。您可能只看到您遇到的问题,因为您没有对编译器运行进行优化。

因此,您inline在 .c 文件中使用 .c 文件的用例没有多大意义,最好只使用static它,即使是额外inline的也不会给您带来太多好处。

于 2013-04-26T21:41:50.760 回答
46

C99 内联语义经常被误解。说明inline符有两个目的:

首先,作为static inlineextern inline声明的编译器提示。如果删除说明符,语义保持不变。

其次,在 raw inline(即没有staticor extern)的情况下,提供内联定义作为外部定义的替代,外部定义必须存在于不同的翻译单元中。不提供外部是未定义的行为,通常表现为链接失败。

如果您想将一个函数放入一个共享库中,这将特别有用,同时也使函数体可用于优化(例如内联或特化)。假设一个足够聪明的编译器,这使您可以恢复 C++ 模板的许多好处,而不必跳过预处理程序。

请注意,这比我在这里描述的要混乱一些,因为有另一个文件范围非内联外部声明将触发 Jens 的回答中描述的第一种情况,即使定义本身inline不是extern inline. 这是设计使然,因此您可以在头文件中有一个内联定义,您可以通过为外部声明添加一行来将其包含到提供外部定义的源文件中。

于 2013-04-27T16:56:11.253 回答
3

这是因为 GCC 处理内联函数的方式。GCC 执行内联替换作为优化的一部分

要消除此错误static,请在 inline 之前使用。使用static关键字强制编译器内联该函数,使程序编译成功。

static inline int func(int i) {
 return i+1;
}
...
i = func(i);
于 2019-02-25T22:52:26.653 回答