C99中的inline,static,extern

时间:2016-01-22 02:05:17

标签: c

请不要在这里重定向到那里的答案 - 我已经阅读了它们,以及其他所有在互联网上的答案,包括标准,但我仍然感到困惑(大多数情况下,我认为是因为技术词汇的重叠,英语单词和语言关键词)。

让我直截了当地说,在C99中,用于功能

static:不要产生任何外部符号

extern(隐式):如果此翻译单元中没有定义,编译器会生成在链接期间解析的引用

现在使用inline。据我所知,由于编译器可能选择内联或不内联,因此问题很复杂。

  • 如果编译器决定内联,显然实现必须在编译时可见
  • 如果编译器决定不内联,链接了哪个函数,以及该代码在哪个翻译单元中生效?

我可以通过两种不同的方式看到这一点:

  1. 如果编译器决定不在某个调用站点内联函数,则在同一个转换单元内生成非内联对象代码。不会为此导出外部符号。
  2. 如果编译器决定不在某个调用站点内联函数,那么这就像普通函数一样,并且必须有一个导出外部符号并包含实现该函数的目标代码的转换单元。
  3. static inline似乎是#1的答案:

    • 如果编译器决定内联static inline函数,那就去吧。 static存储说明符与非内联函数的使用一致,因为不会产生外部符号。由于是这种情况,如果编译器决定在翻译单元中的每个调用站点内联static inline函数,则无需生成独立的目标代码。
    • 如果编译器决定不在某个调用站点内联static inline函数,则它可以在翻译单元内生成独立的目标代码,并且不会为其导出外部符号。

    据我所知,extern inline / inline是#2的答案:

    • 所有inline(没有externstatic)的行为与#2相同。如果编译器实际上没有内联它们,那么在链接时需要链接外部实现。
    • 实际导出要链接的符号的翻译单元 必须声明为extern inline 我认为这是最重要的 令人困惑,因为正常函数的extern关键字表现在 几乎完全相反的方式

    这是对的吗?

    相关链接,但仍留下模糊的角落:

    Is “inline” without “static” or “extern” ever useful in C99?

    extern inline

    The New C: Inline Functions

1 个答案:

答案 0 :(得分:2)

您对此的全面理解是正确的。

  

实际导出要链接的符号的翻译单元必须声明为extern inline。我认为这是最令人困惑的,因为正常函数的extern关键字的行为几乎完全相反

是的,这是该语言的一个不幸部分,但你有权使用它。

作为一小部分琐事(希望不要混淆你),GNU gcc 使用来处理“内联”和“外部内联”与C99 / C11标准对待它们的方式完全相反。在这种情况下,GNU会将“内联”解释为“使用此定义以内联 AND 生成此函数的外部,外部可见定义”,并将“extern inline”视为“只使用此定义进行内联;如果没有内联,则发出对函数的extern引用(必须在别处定义)”。

无论出于何种原因,C99标准选择交换“内联”和“外部内联”的含义,现在我们坚持使用它。

注意:快速测试表明,如果不通过-std = c99 / c11或-fno-gnu89-inline,GNU gcc v4.9.2将默认采用“GNU”方式(-fgnu89-inline)。在那时和GNU gcc v5.2.1之间的某个时间它发生了变化,因为v5.2.1将默认为-fno-gnu89-inline(即标准的C99 / C11方式)。