★関数(再帰呼び出し1)★


ここからは、プログラムの技法の1つである「再帰呼び出し」について説明します。

便利な考え方ですが、良く分からずに使うとプログラムが止まってしまいます。

まずは、仕組みから説明しましょう。


「再帰呼び出し」とは、実行中の関数の中で、その関数を再度呼び出すことを指します。

言葉だけでは分かりづらいので、一番単純な例を書きます。

※まだ実行はしないで下さい。

<sample program 147-01>

int main(void)
{
    main();

    return 0;
}

意味の無いプログラムですが、main関数の中でmain関数を呼び出しています。

とりあえず実行してみましょうか。

<実行結果>


私の環境ではこのような結果になってしまいまいした・・・


main関数の実行中にmain関数を呼び出す訳ですから、いつまで経ってもプログラムが終わりません。

いわゆる形を変えた無限ループのようなものです。

しかし、無限ループであれば途中で止まったりせず、無限に実行し続けるはずです・・・

では、どのような仕組みになっているか説明します。


関数が呼び出される時には、戻る場所(実際はプログラムのアドレス)というものが保存されます。

大体、呼び出された次の行が設定されます。

<sample program 147-01>

int main(void)
{
    main();

    return 0; /* ←ここが戻り場所 */
}

最初のmain関数の実行で、戻り場所が設定され、自分自身(main関数)を呼び出します。

すると、またmain関数を呼び出そうとするので、新しい戻り場所を追加します。

これを繰り返す内に、戻り場所を設定するメモリ領域(スタックといいます)が不足し、プログラムがおかしくなってしまいます。

当然気づいている人もいると思いますが、コンパイルした時点で警告が出ています。

  warning C4717: 'main': すべてのコントロールのパス、関数を回帰するとランタイム スタック オーバーフローが発生します。

「スタックオーバーフロー」という言葉が出ています。

「スタック」があふれてしまい、プログラムが実行出来なくなるということです。

※スタックについてはデータ構造の章で説明します。


では、だいたい何回くらいで止まっているのでしょうか?

次のプログラムで試してみましょう。

<sample program 147-02>

#include <stdio.h>

int main(void)
{
    static int counter;

    counter++;

    printf("%d\n", counter);

    main();

    return 0;
}

static変数を使えば、関数の呼び出し回数を数えることが出来ます。

では、実行してみましょう。









































<実行結果>

1
2
3
4
・
・
・
4847
4848
4849

私の環境では、4849回で止まってしまいました。

この数字は、この実行環境では必ず4849回再帰呼び出しが出来ることを保証するものではありません。

関数内のローカル変数の有無でも変わってしまいます。

再帰呼び出しには限度があることを理解しておいてください。


次へ

戻る

目次へ