私はCを学ぼうとしています。いくつかのコードを読んでいると、次のような行に出くわしました。
__inline__ void () ...
__inline__
意味?そのWordを関数の前に置くと、どのように違いますか?
__inline__
は非標準拡張子です。通常、これはコンパイラに「この関数をインライン化する」ことを伝えますが、非標準の拡張機能であるため、これがどのコンパイラにあるかを知らない限り、確実に言うことはできません。
インライン化とは、関数呼び出しを削除し、その内容を呼び出しが行われる場所に直接配置することです。これにより、多くの場合、関数を呼び出すオーバーヘッドがなくなります。コードの膨張(コードが大きくなりすぎてキャッシュに収まらない)のため、常に最適であるとは限りません。そのため、ほとんどのコンパイラはすべてのインラインディレクティブを無視し、最善と思われることを実行します。 これは良いことです。私たち人間はそのようなことは非常に苦手であり、コンパイラにその仕事をする方法を教えることは通常悪い習慣と考えられています。
インライン化は、特にヘルパー関数が存在する場合、重要な最適化です。 2つのintのうち小さい方を返す関数を想像してみてください。
int min(int x, int y)
{
return (x < y) ? x : y;
}
この関数をコードで使用した場合、ここで実際に関数呼び出しを行うのは非常に時間の無駄になります。もしわたしが持っていたら:
int a = /* some calculation */;
int b = /* some other calculation */;
int minCalc = min(a, b);
そして、コンパイラーがその関数をインライン化すると、コードは次のようになります。
int a = /* some calculation */;
int b = /* some other calculation */;
int minCalc = (a < b) ? a : b;
これにより、関数を呼び出すオーバーヘッドがなくなります。ここから、コンパイラーが通常は関数呼び出しの背後に隠されているコードを直接操作できるようになるため、さらに多くの最適化を行うことができます。ご覧のとおり、大きな関数があり、コンパイラーにそれをどこにでもインライン化させると、コードサイズが非常に速く非常に大きくなる可能性があります。実際には実行速度が低下します。
関数をインライン化する必要があることをコンパイラーに示すために使用された標準のinline
キーワードがありますが、最近のほとんどのコンパイラーは、関数をインライン化するためのヒントとしてそれを認識していません。
ただし、inline
には重要な副作用があり、これは便利です。関数がinline
としてマークされている場合、複数の変換単位にわたる同じ関数の複数の定義はエラーではありません。代わりに、単一の関数定義が選択され、他の定義は破棄され、同じであると見なされます(これが実際にであることを確認するのはあなた次第ですはい!)。これにより、ODR違反エラーのリスクを冒すことなく、ヘッダーファイル内で関数を定義できます。
インラインは、関数をインライン化するためのコンパイラへの提案です。関数のコードブロックとcall
命令を使用する場所で生成する代わりに、生成されたコードをその関数が呼び出される場所で効果的にカットアンドペーストします。
これは通常、単なる提案です。タイトループで呼び出された場合はパフォーマンスが向上しますが、通常はメモリ使用量が増加し、一般的にパフォーマンスに悪影響を与える可能性があります。関数をインライン化するかどうかはコンパイラーが独自に決定します。「プログラマーがこれをインライン化することを提案する」ことを考慮に入れる場合がありますが、(ほとんどのコンパイラーでは)関数をインラインとして宣言するだけでは保証されません。
コンピュータサイエンス では、インライン関数は プログラミング言語 構造であり、- コンパイラ 特定の関数で インライン展開 を実行する必要があります。言い換えると、コンパイラーは、関数が使用されるコード内のすべての場所に関数の完全な本体を挿入します。
ISO C89プログラムにインクルードするヘッダーファイルを作成する場合は、
inline
の代わりに__inline__
を作成してください。 代替キーワード を参照してください。
__inline__
宣言は、関数が呼び出される場所はどこでも、代わりに関数を「インライン化」することをコンパイラーに通知します。インライン化はマクロの使用に似ています。コードは、関数を呼び出した場所で正しく記述したかのように展開されます。
詳細については、 GNU docs を参照してください。
基本的に、これはコンパイラへのヒントです。この関数を使用すると、コードを直接挿入できる可能性があることをお勧めします。
これを行うと、関数呼び出しのオーバーヘッドが回避されるため、より効率的になる可能性があります。しかし、最終的に、コンパイラーは、コードサイズ、指定された最適化オプション、および少しのブードゥーの組み合わせを使用して、このヒントを尊重するかどうかを決定します実際には。
ブードゥービットは最も紛らわしい部分です。 :)動作するために、必ずしも__inline__
(またはより標準的なインライン)に依存する必要はありません。速度が本当に気になる場合は、代わりにアルゴリズムを最適化するか、コードを再編成してください。