当我try 构建此代码时
inline void f() {}
int main()
{
f();
}
使用命令行
gcc -std=c99 -o a a.c
我得到一个链接器错误(未定义对f
的引用).如果使用static inline
或extern inline
而不是inline
,或者使用-O
编译(因此函数实际上是内联的),错误就会消失.
C99标准第6.7.4(6)段似乎对这种行为进行了定义:
如果翻译单元中某个函数的所有文件范围声明都包含不带
extern
的inline
函数说明符,则该翻译单元中的定义是内联定义.内联定义不为函数提供外部定义,也不禁止在另一个翻译单元中使用外部定义.内联定义提供了外部定义的替代方案,翻译器可以使用外部定义在同一翻译单元中实现对函数的任何调用.未指定对函数的调用是使用内联定义还是外部定义.
如果我正确理解了所有这些,那么在上面的示例中,一个函数定义为inline
的编译单元只有在存在同名外部函数的情况下才能进行一致编译,而且我永远不知道是否调用了我自己的函数或外部函数.
这样的行为不是很愚蠢吗?在C99中定义一个没有static
或extern
的函数inline
有用吗?我是不是遗漏了什么?
答案摘要
当然,我错过了什么,而且这种行为并不愚蠢
作为Nemo explains,我们的 idea 是将函数的definition
inline void f() {}
在头文件中,只有declaration
extern inline void f();
在相应的.c文件.只有extern
声明触发外部可见二进制代码的生成.事实上,inline
在计算机中是没有用的.c文件——它只在标题中有用.
正如这rationale of the C99 committee quoted in Jonathan's answer篇文章所解释的那样,inline
都是关于编译器优化的,这些编译器优化要求函数的定义在调用点是可见的.这只能通过将定义放在头中来实现,当然头中的定义不能在编译器每次看到它时都发出代码.但是,由于编译器没有被强制实际内联函数,因此必须在某个地方存在外部定义.