このコードをビルドしようとすると
inline void f() {}
int main()
{
f();
}
コマンドラインを使用する
gcc -std=c99 -o a a.c
リンカエラーが発生します(への未定義の参照f)。エラーは、単にの代わりにstatic inlineまたはを使用した場合、またはコンパイルした場合に消滅します(そのため、関数は実際にはインライン化されています)。extern inlineinline-O
この動作は、C99標準の6.7.4(6)項で定義されているようです。
変換単位内の関数のすべてのファイルスコープ宣言に
inline関数指定子が含まれていないextern場合、その変換単位内の定義はインライン定義です。インライン定義は、関数の外部定義を提供せず、別の翻訳単位での外部定義を禁止しません。インライン定義は、外部定義の代替手段を提供します。トランスレーターは、同じ定義の関数への呼び出しを実装するために使用できます。関数の呼び出しでインライン定義を使用するか外部定義を使用するかは指定されていません。
これらすべてを正しく理解している場合inline、上記の例のように定義された関数を持つコンパイル単位は、同じ名前の外部関数もある場合にのみ一貫してコンパイルされ、自分の関数または外部関数が呼び出されるかどうかはわかりません。
この振る舞いは完全に行き詰まっていませんか?C99 inlineなしで、staticまたはexternC99で関数を定義することは、これまでに有用ですか?何か不足していますか?
回答のまとめ
もちろん、私は何かを逃していた、そしてふるまいはふざけない。:)
以下のようニモを説明し、アイデアが入れてある定義関数のを
inline void f() {}
ヘッダーファイルと宣言のみ
extern inline void f();
対応する.cファイル内。extern宣言だけが、外部から見えるバイナリコードの生成をトリガーします。実際inline、.cファイルではは使用されていません。ヘッダーでのみ役立ちます。
以下のようジョナサンの答えの中で引用されたC99委員会の根拠 explicates、inlineコールのサイトに表示されるように関数の定義が必要なコンパイラの最適化についてのすべてです。これは、ヘッダーに定義を配置することによってのみ達成できます。もちろん、ヘッダー内の定義は、コンパイラーによって認識されるたびにコードを発行してはなりません。しかし、コンパイラーは実際に関数をインライン化する必要がないため、外部定義がどこかに存在している必要があります。
inlineせずにstaticしてexternいるが、。残念ながら、これらの問題はいずれもその質問ではカバーされていません。