[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.31 マクロと同程度の速さのインライン展開関数

関数を inline と宣言することで、その関数のコードを呼出し箇所に 統合することを GNU CC に指示する。これにより、関数呼出しの負荷を 削除するので実行が速くなる。さらに、実引数値のどれかが定数であれば、 それらの値が既知であることにより、 インライン指定のついた関数のコードを全て含める必要が無いように、 コンパイル時のコードの単純化が可能になる。 インライン展開によりコードサイズがどうなるかは予測が難しい。 インライン展開により、オブジェクトコードは大きくなることもあるし、 小さくなることもある。個々の場合による。 関数のインライン展開は最適化の一つであり、最適化付きコンパイルの場合に しか実際には機能しない。 ‘-O’ を指定しなければ、実際にはどの関数もインライン展開されない。

関数のインライン展開を宣言するには、その宣言で inline という キーワードを以下のように使う。

 
inline int
inc (int *a)
{
  (*a)++;
}

(ANSI C に準拠するプログラムで取り込まれるヘッダファイルを 各場合は、inline の代わりに __inline__ と書くようにする。 See section もう一組のキーワード。) 「充分単純」な関数は、‘-finline-functions’ オプションを 指定することで、全てインライン展開関数とすることができる。

関数定義中である特定の使い方をしていると、インライン展開に 適さなくなることに注意。そういう使い方には次のものがある。 varargs を使っている、alloca を使っている、可変長データ型を 使っている(see section 可変長配列)、計算形 goto を 使っている(see section ラベルの値)、非局所 goto を 使っている、入れ子関数を使っている(see section 入れ子関数)。 ‘-Winline’ を指定すると、inline 付きの関数が 置き換え可能でない場合は警告を出し、可能でない理由を表示する。

C と Objective C では、C++ とは違って、キーワード inline は、 関数のリンケージには影響しないことに注意。

GNU CC は、C++ プログラムのクラス本体内で定義されているメンバ関数は、 明示的に inline と宣言されていなくても、自動的にインライン展開 する。(この効果をなくすには、‘-fno-default-inline’ オプションを 指定する。see section Options Controlling C++ Dialect.)

ある関数がインライン展開関数であり static でもあるとき、 その関数への呼出しが全て呼出し側に統合されて、かつその関数のアドレスが 使われることがない場合は、関数自身のアセンブラコードは決して 参照されることがない。この場合、GNU CC は、‘-fkeep-inline-functions’ を 指定しない限り、その関数のアセンブラコードを実際には出力しない。 呼出しの中には様々な理由(特に、関数定義の前にある呼出しや、 関数定義内の再帰呼出しは統合が不可能である)に統合できない。 統合されない呼出しがあると、その関数は通常のようにアセンブラコードに コンパイルされる。関数は、プログラムがそのアドレスを参照している場合も コンパイルされなければならない。インライン展開が不可能だからである。

インライン関数が static でない場合は、コンパイラは他の ソースファイルからの呼出しがあることを想定しなければならない。 グローバルシンボルはどんなプログラムでも一箇所でしか定義できないので、 その関数は他のソースファイルで定義してはならない。このため、他のソース ファイルにある呼出しは統合できないのである。このため、 非 static インライン関数は常に普通の形でコンパイルされる。

関数定義に inlineextern の両方を指定すると、その定義は インライン展開でのみ使われる。関数定義自体がコンパイルされることは 決してない。その関数のアドレスを明示的に参照してもコンパイルされないのである。 そのようなアドレスは、関数を宣言しただけで定義していない場合のように、 外部参照になる。

inlineextern をこのように組み合わせると、 ほとんどマクロと同じ効果になる。これの使い方は、この二つのキーワードを 付けた関数定義をヘッダファイルに置いておき、この定義のコピー (inlineextern を付けないもの)をライブラリファイルに 置いておくのである。ヘッダファイルの方の関数定義は、この関数の ほとんどの呼出しをインライン展開されるようにする。この関数のそれ以外の 使い方をすれば、ライブラリ中の一個のコピーの方を参照する。

GNU C は、最適化を行わない場合はどんな関数もインライン展開しない。 こういう場合にインライン展開した方が良いのかどうかはっきりしていない。 だが、最適化を行わない場合の正しい実装が難しいということが判ったので、 我々は簡単な方にした。すなわち、インライン展開をしないことにした。


This document was generated using texi2html 1.78.