C99中的内联、静态、外部
请不要将我的答案重定向到这里——我已经阅读了这些答案,以及互联网上的其他答案,包括《标准》,但我仍然感到困惑(我认为主要是因为技术词汇、英语词汇和语言关键词的重叠)C99中的内联、静态、外部,c,C,请不要将我的答案重定向到这里——我已经阅读了这些答案,以及互联网上的其他答案,包括《标准》,但我仍然感到困惑(我认为主要是因为技术词汇、英语词汇和语言关键词的重叠) 让我直截了当地说,在C99中,函数的: 静态:不生成任何外部符号 extern(隐式):如果此翻译单元中没有定义,编译器将生成一个在链接期间解析的引用 现在使用内联。据我所知,这个问题很复杂,因为编译器可能选择内联,也可能不选择内联 如果编译器决定内联,很明显,实现必须在编译时可见 如果编译器决定不内联,将链接哪个函数,该代码
让我直截了当地说,在C99中,函数的:
静态
:不生成任何外部符号
extern
(隐式):如果此翻译单元中没有定义,编译器将生成一个在链接期间解析的引用
现在使用
内联
。据我所知,这个问题很复杂,因为编译器可能选择内联,也可能不选择内联
- 如果编译器决定内联,很明显,实现必须在编译时可见
- 如果编译器决定不内联,将链接哪个函数,该代码位于哪个翻译单元中
我可以用两种不同的方式来回答这个问题:
静态内联
似乎是#1的答案:
- 如果编译器决定内联一个
函数,那么就执行它。静态内联
存储说明符与它在非内联函数中的使用是一致的,因为它不会产生外部符号。由于这种情况,如果编译器决定在翻译单元内的每个调用站点内联一个静态
函数,那么它不需要生成独立的目标代码静态内联
- 如果编译器决定不在某个调用站点内联
函数,那么它可以在翻译单元内生成独立的目标代码,并且不会为其导出任何外部符号静态内联
据我所知,
extern-inline
/inline
是#2:
- 所有
(不带inline
或extern
)的行为类似于#2。如果编译器实际上没有内联它们,那么在链接时需要链接一个外部实现static
- 实际导出要链接的符号的翻译单元
必须声明为
我认为这是最重要的 混淆,因为正常函数的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方式).很抱歉回复太晚。这确实是一件有趣(也是非常不幸)的琐事!再次感谢!