次のように、関数を.c(ヘッダー宣言なし)で定義しました。
inline int func(int i) {
return i+1;
}
次に、以下の同じファイルで使用します:
...
i = func(i);
そして、リンク中に「 'func'への未定義の参照」を取得しました。どうして?
C99インラインセマンティクスはしばしば誤解されます。 inline
指定子には2つの目的があります。
最初に、static inline
およびextern inline
宣言の場合のコンパイラーのヒントとして。指定子を削除しても、セマンティクスは変更されません。
第二に、未加工のinline
(つまりstatic
またはextern
なし)の場合、別の場所に存在する必要がある外部定義の代替としてインライン定義を提供します。翻訳単位。外部のものを提供しないことは未定義の動作であり、通常はリンクの失敗として現れます。
これは、関数を共有ライブラリに入れたいが、関数本体を最適化(インライン化や特殊化など)できるようにする場合に特に便利です。十分にスマートなコンパイラを想定すると、これにより、プリプロセッサフープをジャンプすることなく、C++テンプレートの多くの利点を回復できます。
定義自体がextern inline
ではなくinline
であっても、Jensの答えで説明されているように、別のファイルスコープの非インライン外部宣言が最初のケースをトリガーするため、ここで説明するよりも少し厄介です。これは仕様によるものであるため、ヘッダーファイルに単一のインライン定義を含めることができます。これは、外部宣言に1行追加することで、外部定義を提供するソースファイルに含めることができます。
これは、GCCがインライン関数を処理する方法が原因です。 GCCは最適化の一部としてインライン置換を実行します。
このエラーを削除するには、インラインの前にstatic
を使用します。 static
キーワードは、静的キーワードを使用するコンパイラーに強制的にコンパイラーに、プログラムを正常にコンパイルさせるこのインライン関数を強制します。
static inline int func(int i) {
return i+1;
}
...
i = func(i);