如何正确内联静态库

我正在重写我的一个小C数学库,它最终会成为用户的静态库,并希望从我的矢量数学界面的内联中受益。

我有以下内容:

[mymath.h]

... ... extern float clampf( float v, float min, float max ); ... ... 

[mymath.c]

 inline float clampf( float v, float min, float max ) { if( v  max ) v = max; return v; } 

由于我的库是静态的,我只是要向用户提供.h (和.lib ),在编译时是否会在程序中内联clampf函数?

我做的是正确的事情但是在.h声明了函数extern并且在.c内联了吗?

你几乎是正确的。 你实际上倒退了; 对于内联函数,您必须将inline定义放在头文件中,并将extern声明放在C文件中。

 // mymath.h inline float clampf( float v, float min, float max ) { if( v < min ) v = min; if( v > max ) v = max; return v; } // mymath.c #include "mymath.h" extern float clampf( float v, float min, float max ); 

您必须将定义(完整正文)放在头文件中,这将允许任何包含头文件的文件能够在编译器选择时使用内联定义。

您必须将extern声明(原型)放在源文件中,以告诉编译器在库中发出该函数的外部版本。 这为您的库中的非内联版本提供了一个位置,因此编译器可以在内联函数或使用通用版本之间进行选择。

请注意,这可能不适用于MSVC编译器,MSVC编译器通常对C的支持非常差(并且几乎没有支持C99)。 对于GCC,您必须为旧版本启用C99支持。 Modern C编译器默认支持此语法。

替代方案:

您可以将标题更改为具有static inline版本,

 // mymath.h static inline float clampf(float v, float min, float max) { ... } 

但是,这不提供函数的非内联版本,因此可能会强制编译器为每个转换单元创建此函数的副本。

笔记:

  1. C99内联规则并不完全直观。 文章“ C中的内联函数 ”( 镜像 )详细描述了它们。 特别是,请跳到底部并查看“使用内联函数的策略”。 我更喜欢方法#3,因为GCC已经默认为C99方法一段时间了。

  2. 从技术上讲,您永远不需要在函数声明(或定义)上放置extern ,因为extern是默认值。 我把它放在那里强调。

您应该在.h文件中将函数定义为static inline

 static inline float clampf( float v, float min, float max ) { if( v < min ) v = min; if( v > max ) v = max; return v; } 

.c文件中必须不存在该函数。

编译器可能决定不内联函数,但使其成为正确的函数调用。 因此,每个生成的.o文件都可能包含该函数的副本。