Oracle Solaris Studio 12.2: C ユーザーガイド

D.1.10 inline 関数

6.7.4 関数指示子

1999 C ISO 標準で定義されているインライン関数は、完全にサポートされています。

C 標準によると、インラインは C コンパイラに対する推奨に過ぎません。C コンパイラは、何もインライン化しないこと、または実際の関数への呼び出しをコンパイルすることを選択できます。

最適化レベルを -xO3 かそれ以上に設定してコンパイルする場合以外は、Solaris Studio C コンパイラは C の関数呼び出しをインライン化しません。なおかつ、オプティマイザのヒューリスティック (発見的手法) によってインライン化に利点があると判断された場合のみ、インライン化します。C コンパイラは、関数のインライン化を強制する方法を用意していません。

static インライン関数は単純です。インライン関数指定子によって定義された関数を、参照時にインライン化するか、実際の関数を呼び出すかのどちらかです。コンパイラは、参照ごとにどちらを実行するかを選択できます。コンパイラは -xO3 以上の場合、インライン化に利点があるかどうかを判定します。インライン化の利点がない場合 (または最適化が -xO3 未満の場合)、実際の関数への参照がコンパイルされ、関数定義がコンパイルされてオブジェクトコードの一部になります。プログラムが関数のアドレスを使用している場合は、実際の関数がコンパイルされてオブジェクトコードの一部になり、インライン化されないことに注意してください。

extern インライン関数はより複雑です。extern インライン関数には 2 つの種類があります。インライン定義および extern インライン関数です。

インライン定義とは、キーワード inline を使い、static または extern キーワードなしで定義された関数です。ソース (またはインクルードファイル) 内に含まれるあらゆるプロトタイプにも、static または extern キーワードなしでキーワード inline が含まれます。インライン定義に対して、コンパイラは関数のグローバル定義を作成してはいけません。このことは、インライン化されないインライン定義へのあらゆる参照は、どこか他の場所で定義されたグローバル関数への参照になることを意味します。言い換えると、この変換ユニット (ソースファイル) をコンパイルすることで作成されたオブジェクトファイルには、インライン定義に対応するグローバルシンボルは含まれません。インライン化されない関数へのあらゆる参照は、リンク時にほかのオブジェクトファイルまたはライブラリから提供される extern (大域) シンボルになります。

extern インライン関数は、extern 記憶クラス指定子 (つまり、関数定義とプロトタイプの一方または両方) を持つファイルスコープ宣言によって宣言されます。extern インライン関数の場合、コンパイラはその関数に対応するグローバル定義を、結果として生成されるオブジェクトファイルの中で提供します。コンパイラは、関数定義の提供元である変換ユニット (ソースファイル) の中で観察された関数へのすべての参照をインライン化するか、グローバル関数を呼び出すかを選択できます。

関数呼び出しが実際にインライン化されるかどうかに依存する任意のプログラムの動作は、未定義です。

外部リンケージを持つインライン関数が、変換ユニットのどこであっても静的変数を宣言または参照してはいけないことにも注意してください。

D.1.10.1 インライン関数に対する Solaris Studio C コンパイラと gcc の互換性

ほとんどのプログラムで、extern インライン関数に関する gcc の実装に対して Solaris Studio C コンパイラが互換性を維持できるようにするには、-features=no%extinl フラグを使用します。このフラグが指定されている場合は、Solaris Studio C コンパイラはあたかも static インライン関数と宣言されたかのように、関数を処理します。

この手法が互換性を維持できない状況の 1 つは、関数のアドレスを取る場合です。gcc ではこのアドレスはグローバル関数のアドレスになりますが、Sun のコンパイラではローカルの static 定義アドレスが使用されます。