C99 inline
语义很微妙 - 事实上,语言的整个部分(存储持续时间与链接,暂定和内联定义)是一团糟。
尽管inline
在包含存储类说明符(static
或extern
)的定义中充当编译器提示,并且基本上可以忽略,但如果不存在说明符,则语义会更改。
像inline int fun(void) { ... }
的定义做两两件事:
首先,它声明与外部链接的标识符,但不提供相应的外部定义。这意味着这种定义必须由不同的翻译单位提供,否则我们最终会出现未定义的行为(可能表现为未能链接)。
其次,它提供了一个内联定义,它是外部替代的替代。由于函数体在当前的翻译单元中可见,因此编译器可以使用它来内联函数或类型专门化。
为了获得外部定义,直到fairly recently,我认为有必要在另一个翻译单元(或假的,与4行预处理器代码)重复函数定义。
然而,这不是必要的:一个单一的代码线 - 其包括extern
说明符的功能的重新声明 - 是足以使直列式定义到外部的一个。
在你的榜样,这将意味着将
inline int foo(void)
{
return 42;
}
成一个头文件foo.h
并提供与内容
#include "foo.h"
// force definition to be external instead of inline
// I believe inline could be omitted, but it doesn't hurt
extern inline foo(void);
为什么这是有用的源文件foo.c
?由于C缺乏模板,所以通用代码通常会带来性能损失,因为您需要使用void*
和函数指针(或更复杂的情况下,vtables)来伪造泛型。但是,只有当相关函数定义在当前翻译单元中可见时,足够智能的优化程序才能获得模板的大多数(可能全部)性能优势,但是(在没有链接时优化的情况下)。
尽管可以通过在头文件中添加static
定义来实现此目的,但这可能会使代码大小增加到与C++模板相同的不可接受的级别。
相比之下,使用C99 inline
函数,编译器可以自由地忽略内联定义而偏向外部定义,甚至可以驻留在共享库中。
功能的一个很好的例子是qsort()
,stdlib.h
的内联定义和libc.so
的外联定义。 qsort()
没有先验原因比std::sort()
慢。
什么是编译器? –
在gcc 4.7版上工作得很好。 – unxnut
什么是错误信息? (它适用于我与海湾合作委员会,但不与“gcc -std = c99 -pedantic”。) –