.c 文件中的 C99 内联函数

Posted

技术标签:

【中文标题】.c 文件中的 C99 内联函数【英文标题】:C99 inline function in .c file 【发布时间】:2013-04-21 03:56:05 【问题描述】:

我在 .c 中定义了我的函数(没有头声明),如下所示:

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

然后在下面的同一个文件中我使用它:

...
i = func(i);

在链接过程中,我得到了“对 'func' 的未定义引用”。为什么?

【问题讨论】:

要么设为static,要么提供链接器可以找到的非内联定义。 另见***.com/questions/6312597 【参考方案1】:

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

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

static inline int func(int i) 
 return i+1;

...
i = func(i);

【讨论】:

但是如何处理成员函数呢? @Piroxiljin:C 没有成员函数,只有 C++ 有。根据 Jens 对这个问题的回答,inline 的含义在 C 和 C++ 之间有所不同。 嗯。这里发生了什么?我一直认为staticinline 由于某种原因是正交的。如,static 暗示它必须存在,而inline(根据定义)不存在。 (“不存在”是指定义的符号,因为它会被内联)。【参考方案2】:

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

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

int func(int i);

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

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

【讨论】:

我的错,没有inlineextern 文件范围声明确实 强制定义不是内联的 我有一个问题,为什么关闭优化后会出现这种情况?当我使用 gcc -O1 选项打开它时,它只会编译,gcc 优化中的哪个选项提供了以正确方式编译的代码? @Lazureus,当你用-O0 编译时,我想你的意思是,gcc 通常不会内联任何函数。那么你必须在某处定义了符号,否则它找不到任何inline declare-defined 函数。【参考方案3】:

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

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

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

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

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

【讨论】:

这个答案有点过时 - 我以为 Jens 的答案有误,但结果我错了...... 实际上,解释什么时候语义有用是一个有价值的答案(至少对我来说)。

以上是关于.c 文件中的 C99 内联函数的主要内容,如果未能解决你的问题,请参考以下文章

强制函数在Clang / LLVM中内联

链接器可以内联函数吗?

C内联函数的内外链接的区别

Go语言中的内联函数

C内联函数的内外链接的区别

内联函数