C11标准下:inline函数无inline定义时能否被内联?
先明确C11标准的相关条款:
C11 6.7.4 p6:
使用inline函数说明符声明的函数是inline function(内联函数)。
C11 6.7.4 p7:
任何具有内部链接的函数都可以是inline function。对于具有外部链接的函数,需遵循以下限制:若函数使用inline函数说明符声明,则必须在同一翻译单元中定义。若某函数在一个翻译单元中的所有文件作用域声明都包含不带extern的inline说明符,则该翻译单元中的定义为inline definition(内联定义)。
问题
如果某函数是inline function,但当前翻译单元中没有其inline definition(例如声明为extern inline int foo(){...},该声明不满足inline definition的要求,会生成外部定义,foo是inline function但其定义并非inline definition),调用foo();时仍可被内联而非作为函数调用吗?
换言之,函数被内联的可能性取决于它是inline function,还是它存在inline definition?
回答
首先要明确:编译器是否内联一个函数属于实现定义的行为——C标准并没有强制要求编译器必须内联某个函数,哪怕它是inline function或者有inline definition。结合标准语义和常见编译器行为,可以得出以下结论:
当翻译单元中只有
extern inline定义(非inline definition)时,该定义属于外部链接。编译器通常可选择将调用转为外部函数调用,但如果能直接复用当前单元内extern inline的代码实现内联,标准也不禁止这种行为,最终是否内联取决于编译器的优化策略。当翻译单元中存在inline definition(所有文件域声明均为不带extern的inline)时,这个定义是专为当前翻译单元内联优化设计的,编译器会更倾向于将该单元内的调用做内联处理,因为标准明确该定义的作用就是供当前单元内联使用(除非有extern声明覆盖)。
核心总结:
- 被标记为inline function是编译器考虑内联的前提,但不保证一定会内联;
- inline definition的存在,给编译器提供了明确的、仅用于当前单元内联的代码版本,会显著提升内联的可能性;
- 即便只有
extern inline的非inline definition,编译器仍有可能选择内联,但这不属于标准强制要求,完全由编译器优化逻辑决定。
内容的提问来源于stack exchange,提问作者user24723440

