当我尝试构建此代码时
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)段中定义:
如果翻译单元中某个函数的所有文件范围声明都包含不带
inline
的extern
函数说明符,则该翻译单元中的定义为内联定义。内联定义不为函数提供外部定义,也不禁止在另一个翻译单元中使用外部定义。内联定义提供了外部定义的替代方法,翻译器可使用该外部定义在同一翻译单元中实现对该函数的任何调用。未指定对函数的调用是使用内联定义还是外部定义。[如果我正确理解了所有这些内容,则只有在上面的示例中具有定义为
inline
的函数的编译单元,才能在只有相同名称的外部函数的情况下一致地编译,而我永远不知道自己的函数还是外部的函数被调用。
这种行为不是完全愚蠢吗?在C99中定义不带inline
或static
的功能extern
有用吗?我想念什么吗?
当然,我缺少某些东西,而且行为也不愚蠢。 :)
作为Nemo explains,其想法是放置函数的定义
inline void f() {}
在头文件中,只有一个声明
extern inline void f();
在相应的.c文件中。仅
extern
声明触发生成外部可见的二进制代码。而且,在.c文件中确实没有使用inline
-仅在标头中有用。
正如rationale of the C99 committee quoted in Jonathan's answer所阐述的,inline
都是关于编译器优化的,它要求在调用现场可见函数的定义。这只能通过将定义放在标头中来实现,当然,标头中的定义一定不能在每次编译器看到它时都发出代码。但是由于没有强制编译器实际内联函数,因此外部定义必须存在于某个位置。
[当我尝试构建此代码时,内联void f(){} int main(){f();使用命令行gcc -std = c99 -o a a.c我收到链接器错误(对f的未定义引用)。如果我使用...
实际上,这个很好的答案也回答了您的问题,我认为:
摘自标准(ISO / IEC 9899:1999):
>我收到链接器错误(对f
的未定义引用)