C99内联函数在.c文件中

use*_*416 36 c c99

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

inline int func(int i) {
 return i+1;
}
Run Code Online (Sandbox Code Playgroud)

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

...
i = func(i);
Run Code Online (Sandbox Code Playgroud)

在链接期间,我得到了"未定义的引用'func'".为什么?

Jen*_*edt 43

inlineC99中的模型与大多数人的想法略有不同,特别是与C++使用的模型不同

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

int func(int i);
Run Code Online (Sandbox Code Playgroud)

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

所以,你inline在.c文件中使用的用例没有多大意义,更好的是只使用static它,即使是额外的inline也不会给你带来太大的收益.

  • 我有一个问题,为什么在关闭优化时会出现这种情况?当我用gcc -O1选项打开它时它只会编译,gcc优化中的哪个选项提供这个代码以正确的方式编译? (3认同)
  • @Lazureus,当你用`-O0`编译时,我想你的意思是,gcc通常不会内联任何函数.那么你*必须*在某处定义符号,否则它将找不到任何`inline`声明定义的函数. (3认同)

Chr*_*oph 33

C99内联语义经常被误解.在inline符有两个目的:

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

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

如果要将函数放入共享库,还要使函数体可用于优化(例如内联或专门化),这将特别有用.假设一个足够智能的编译器,这使您可以恢复C++模板的许多好处,而无需跳过预处理器箍.

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

  • 实际上,解释何时语义有用是一个有价值的答案(至少对我而言). (7认同)