【问题标题】:What happens with an extern inline function?外部内联函数会发生什么?
【发布时间】:2013-07-06 15:24:18
【问题描述】:

如果我将 .h 文件中的函数定义为

extern int returnaint(void);

在相关的.c文件中定义为

inline int returnaint(void) {
    return 1;
}

并将标题包含在另一个 .c 文件中并使用该功能?当我单独编译这些东西,为每个 .c 文件创建一个目标文件然后链接它们时,是否包含内联函数,或者会发生什么?

我知道编译器可以忽略inline,但是如果它在这种情况下不忽略它呢?

【问题讨论】:

标签: c compiler-construction header linker inline


【解决方案1】:

inline 添加到.c 文件中的函数定义只是多余的。

  • .c 文件的编译单元看到 extern 声明(没有 inline)和 inline 定义。因此它会在目标文件中发出函数的符号。

  • 所有其他编译单元只能看到 extern 声明,因此如果您将最终可执行文件与其他 .o 文件链接,它们可以毫无问题地使用该函数。

事实上,你只是用错了方法。此功能适用于您在.h 文件中拥有inline 定义,每个人都可以看到。这个函数的定义只作为符号的声明,就像extern 一样,但没有定义它。

仅在一个.c 文件(编译单元)中的extern 声明然后确保在那里定义符号。

术语有点混乱,inline definition 充当符号的声明,extern 声明 充当它的定义

【讨论】:

  • 好点。我想我应该将我的内联函数移到标题中! :-)
  • 在定义函数的翻译单元中添加内联有效果。可能的结果是该函数在此编译单元中的用法将被内联。
  • @UweKleine-König,没有。编译器可以随意做任何事情。如果函数的定义是可见的,编译器可能会或可能不会选择内联,只要它遵守“as-if”规则。将inline 添加到该定义中不会改变任何内容。
  • @JensGustedt,这与我的说法并不矛盾。是的,“内联”只是对编译器的提示。但是假设添加该提示在实践中会有所不同,那么该差异恰好适用于同一编译单元中各个函数的用法。
  • 我使用的编译器,主要是 gcc,还有 clang 或 icc,与 inline 没有区别,他们甚至不把它当作提示。为了让他们相信您比他们更了解,您必须使用一些编译标志或使用 __attribute__((allways_inline)) 来有所作为。所以不,不要指望仅仅添加 inline 会改变任何事情。
【解决方案2】:

它不会编译。来自 C11 (ISO/IEC 9899:2011) §6.7.4 函数说明符(已添加重点):

任何具有内部链接的函数都可以是内联函数。对于具有外部功能的 链接,以下限制适用:如果一个函数是用内联函数说明符声明的,那么它也应该在同一个翻译单元中定义。如果所有的 翻译单元中函数的文件范围声明包括内联函数 没有 extern 的说明符,则该翻译单元中的定义是内联的 定义。内联定义不为函数提供外部定义, 并且不禁止在另一个翻译单元中进行外部定义。内联定义 提供了外部定义的替代方案,翻译人员可以使用它来实现 在同一个翻译单元中对函数的任何调用。未指定是否调用 函数使用内联定义或外部定义。140)

140)因为内联定义不同于相应的外部定义和任何其他定义 其他翻译单元中对应的内联定义,所有对应的对象都有静态存储 持续时间在每个定义中也是不同的。

另一个.c文件只从头文件中得到inline函数的声明,但没有得到定义,所以它违反了粗体的规则。

编辑:

正如@Jens Gustedt 所指出的,我之前的解释是错误的,因为在OP 的问题中,函数在头文件中被声明为非内联:

extern int returnaint(void);

所以另一个.c 文件会将其视为普通函数。

【讨论】:

  • 错误答案。其他.c 文件看不到inline .h 中的声明只有extern 而不是inline
猜你喜欢
  • 1970-01-01
  • 2011-06-26
  • 1970-01-01
  • 2020-03-04
  • 2014-09-19
  • 2012-03-07
  • 2013-04-01
  • 1970-01-01
  • 2017-07-12
相关资源
最近更新 更多