2012-04-24 7 views
14

私は、静的ライブラリとして最終的になる小さな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にインラインで宣言していますか?

答えて

16

あなたはそれがほぼ正しいです。あなたは実際にそれを後方に持っています。インライン関数の場合は、ヘッダファイルにinlineの定義を、Cファイルにはexternの宣言を入れる必要があります。

// 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コンパイラではうまく動作しない可能性があることに注意してください。これは一般にCのサポートが非常に悪いです(C99はほぼゼロサポート)。 GCCでは、古いバージョンのC99サポートを有効にする必要があります。最新のCコンパイラは、デフォルトでこの構文をサポートしています。

代替:あなたはstatic inlineバージョンを持っているヘッダーを変更することができます

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

しかし、これは機能の非インラインバージョンを提供していませんので、コンパイラがよいです各翻訳単位に対してこの関数のコピーを作成するように強制されます。

注:

  1. C99のインライン化規則は正確に直感的ではありません。記事「Inline functions in C」(mirror)に詳細が記載されています。特に、下にスキップし、「インライン関数を使用するための戦略」を参照してください。私は方法#3を好む、なぜならGCCは今やC99メソッドにデフォルト設定されているからだ。

  2. externがデフォルトであるため、技術的には、externを関数宣言(または定義)に置く必要はありません。私はそこに重点的に置いています。

+1

私はあなたの答えが間違っていると確信しています。 'inline'という関数を定義し、' static inline'ではなく、その関数が複数のコンパイル単位で使われていると、リンクは失敗します。 GCC 4.6と-std = c99でテストされています。関数定義 'extern inline'を宣言すると動作しますが、これはGCC拡張です。 – kay

+3

@kay:答え全体を読む。あなたは、関数のための 'extern'宣言を翻訳単位のどこかに(すなわちヘッダーにではなく)追加しなければなりません。これにより、非インラインバージョンがそのモジュールで発行されます。 (ヘッダファイルは一般にそのユニットからインクルードされるべきです)C99標準を参照するか、http://www.greenend.org.uk/rjk/tech/inline.htmlを参照してください。 –

+0

私は確信しています:-) – kay

5

あなたは.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ファイルには、関数のコピーが含まれている可能性があります。

+2

正しくリコールすれば、リンカは静的インライン関数の異なるコピーを結合しません。だから、 'inline' /' extern'バージョンに比べて重複したコードになります。 (出血エッジリンカーは、私は重複を排除することができると思うが、彼らはまだ一般的な使用から少し方法です。) –

+3

関数がインラインの場合、関数のすべての呼び出しは、コードが重複しています。これは設計によるものですか? –

+0

@DietrichEppあなたは正しいです。私は(誤って)この重複したコードの削除が標準であると考えました。 – kay

関連する問題