私は、最終的にはユーザー用の静的ライブラリとなる小さな 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 < min ) v = min;
if( v > max ) v = max;
return v;
}
私のライブラリは静的であり、ユーザーには.h
(および)のみを提供する予定なので、コンパイル時に関数はプログラム内でインライン化されますか?.lib
clampf
extern
関数を で宣言し.h
、 でインライン化するのは正しいことでしょうか.c
?
ベストアンサー1
ほぼ正解です。実際は逆です。インライン関数の場合、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 バージョンを生成するように指示するには、ソース ファイルに宣言 (プロトタイプ)を配置する必要がありますextern
。これにより、ライブラリ内に非インライン バージョン用の場所が 1 つ用意されるため、コンパイラーは関数をインライン化するか、共通バージョンを使用するかを選択できます。
これは、MSVC コンパイラではうまく動作しない可能性があることに注意してください。MSVC コンパイラは、一般的に C のサポートが非常に貧弱で (C99 のサポートもほとんどありません) です。GCC の場合、古いバージョンの C99 サポートを有効にする必要があります。最新の C コンパイラは、この構文をデフォルトでサポートしています。
代替:
ヘッダーをバージョンに変更することができますstatic inline
。
// mymath.h
static inline float clampf(float v, float min, float max)
{
...
}
ただし、これは関数の非インライン バージョンを提供しないため、コンパイラは各翻訳単位に対してこの関数のコピーを強制的に作成する可能性があります。
ノート:
C99 のインライン化ルールは、必ずしも直感的ではありません。記事「C のインライン関数「(鏡) で詳細に説明されています。特に、一番下までスキップして「インライン関数を使用するための戦略」を参照してください。GCC はしばらくの間、デフォルトで C99 メソッドを使用しているため、私はメソッド 3 を好みます。
extern
技術的には、関数宣言(または定義)を入れる必要はありませんextern
。これはデフォルトであるためです。