Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C99中的内联、静态、外部_C - Fatal编程技术网

C99中的内联、静态、外部

C99中的内联、静态、外部,c,C,请不要将我的答案重定向到这里——我已经阅读了这些答案,以及互联网上的其他答案,包括《标准》,但我仍然感到困惑(我认为主要是因为技术词汇、英语词汇和语言关键词的重叠) 让我直截了当地说,在C99中,函数的: 静态:不生成任何外部符号 extern(隐式):如果此翻译单元中没有定义,编译器将生成一个在链接期间解析的引用 现在使用内联。据我所知,这个问题很复杂,因为编译器可能选择内联,也可能不选择内联 如果编译器决定内联,很明显,实现必须在编译时可见 如果编译器决定不内联,将链接哪个函数,该代码

请不要将我的答案重定向到这里——我已经阅读了这些答案,以及互联网上的其他答案,包括《标准》,但我仍然感到困惑(我认为主要是因为技术词汇、英语词汇和语言关键词的重叠)


让我直截了当地说,在C99中,函数的

静态
:不生成任何外部符号

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


现在使用
内联
。据我所知,这个问题很复杂,因为编译器可能选择内联,也可能不选择内联

  • 如果编译器决定内联,很明显,实现必须在编译时可见
  • 如果编译器决定不内联,将链接哪个函数,该代码位于哪个翻译单元中

我可以用两种不同的方式来回答这个问题:

  • 如果编译器决定不在某个调用站点内联函数,则在同一个翻译单元内生成非内联目标代码。没有为此导出外部符号
  • 如果编译器决定不在某个调用站点内联函数,则该函数的行为与普通函数相同,并且必须有一个输出外部符号并包含实现该函数的目标代码的转换单元

  • 静态内联
    似乎是#1的答案:

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

    据我所知,
    extern-inline
    /
    inline
    是#2:

    • 所有
      inline
      (不带
      extern
      static
      )的行为类似于#2。如果编译器实际上没有内联它们,那么在链接时需要链接一个外部实现
    • 实际导出要链接的符号的翻译单元 必须声明为
      extern inline
      我认为这是最重要的 混淆,因为正常函数的
      extern
      关键字在 几乎完全相反

    这是正确的吗


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


    您对这一点的总体理解是正确的

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

    是的,这是语言中不幸的一部分,但你有权这样做


    作为一个小细节(希望不会让您感到困惑),GNU gcc使用了来处理“内联”和“外部内联”,与C99/C11标准处理它们的方式完全相反。在这种情况下,GNU将“inline”解释为“使用此定义与内联,并生成此函数的外部可见的越界定义”,并将“extern inline”视为“仅将此定义用于内联;如果没有内联,则向函数发出外部引用”(必须在其他地方定义)”

    无论出于何种原因,C99标准选择交换“inline”和“extern inline”的含义,而现在我们仍坚持使用它


    注:快速测试表明,如果您没有通过-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方式).

    很抱歉回复太晚。这确实是一件有趣(也是非常不幸)的琐事!再次感谢!