最近、宣言されたいくつかの再帰関数を読みましたstatic
。
関数宣言の前に追加するstatic
と、GCCが末尾再帰関数を最適化するのに役立ちますか?これは最適化を取得するために必須ですか?
static
特に関数beingがコンパイラーが再帰呼び出しを最適化するのに役立つはずである理由はわかりません。
すぐに、あなたが見た再帰関数は単にコンパイルユニットの内部にある可能性が高いようです。再帰関数は、プログラムの残りの部分に公開したいよりも豊富なインターフェイスを必要とすることがよくあります。たとえば、再帰呼び出しでのみ使用される追加のパラメーターがある場合や、一般呼び出しからの戻り値が必要な場合があります。コードの残りの部分に提示したい抽象化に適合するように調整されます。したがって、通常、追加のパラメーターのデフォルト値を設定し、一般に再帰関数のインターフェースを外部的に意味のあるものに調整するラッパー関数を作成します。
再帰関数はそれ自体とラッパー関数によってのみ呼び出されるstatic
ため、再帰自体のためではなく、グローバル名前空間がそれで汚染されるのを防ぐために、それを宣言するのが自然です。コンパイラは、静的関数に対してより効率的な呼び出し規約(その特定の関数本体に適合)を使用できる可能性もあります。これは、コンパイラがすべての呼び出しサイトを認識しており、個別にコンパイルされたコードがそれを呼び出すようにするABIに従う必要がないためです。
いいえ、static
再帰の最適化とは何の関係もありません。関数が宣言さstatic
れると、内部リンケージを取得するため、同じ変換ユニット内の他の関数以外から呼び出す/使用することはできません。
静的(つまり内部リンケージ)が関数に与える影響の1つは、特定の関数への直接呼び出しのすべての可能なユースケースが現在の変換ユニットにローカライズされていることをコンパイラーに通知することです。これは確かに特定の最適化に影響を与える可能性があります。たとえば、コンパイラが特定の関数へのすべての呼び出しを変換ユニットにインライン化することを決定した場合(そして、その関数のアドレスが取得されない場合)、関数がスタンドアロン本体を必要としないことがすぐにわかります。または、別の例として、関数が常に1
引数として呼び出される場合、技術的にはこの引数を完全に削除できます。等々。
外部にリンクされた関数を使用すると、このような最適化も可能ですが、プログラム全体に関するグローバルな知識が必要です(そのため、グローバル最適化と呼ばれることがよくあります)。内部でリンクされた機能により、これらすべての可能性が1つの翻訳ユニット内で開かれます。
ただし、末尾再帰の除去などの最適化では、問題にはなりません。