1

以下は、プログラムの後に続く出力を提供するサンプルCプログラムです。

#include<stdio.h>
void newfunc(int n);
int main(void)
{
    newfunc(2);
    return 0;
}
void newfunc(int n)
{
    printf("\n%d",n);
    if(n<50)
    {
        newfunc(2*n);
        printf("\n%d",n);
    }
}

出力を生成します

2
4
8
16
32
64
32
16
8
4
2

しかし、コードによると、13行目の関数呼び出しの後、次 printfは呼び出されていないようです。そして、出力は不自然に見えます。インターネットを検索して、スタックについて何かを見つけました。誰かがなぜこれが起こるのか詳しく説明できますか?

4

3 に答える 3

3

これは基本的な再帰呼び出しです。

nまず、 50 未満の値の場合、関数はn2 回出力され、それ以外の値の場合は 1 回だけ出力されることに注意してくださいn。それはあなたの出力と一致するので、ここで理解する唯一のことは順序です...

2つ目の s の間で再帰呼び出しを行うため、 for の出力は( for )からの出力の 1 行目と 2 行目のにあることに注意してn*2ください。まあ、それはあなたの出力とも一致します。nn < 50printf

これは予想通りです。

スタックについてインターネットで見つけた部分は、呼び出しスタックを参照しています。関数から戻るために、プログラムは関数が呼び出されたときの場所を追跡する必要があります。この情報は、「呼び出しスタック」または「実行スタック」と呼ばれるメモリの特別な部分の「最後」に書き込まれます。そしてそれはスタックから取り除かれます(つまり、関数が戻るときに「終了」が移動されます)。呼び出しパラメーターもスタックに記録されます。

この種のスタッキングは、再帰に不可欠です。

したがって、プログラムを呼び出すとnewfunc(2)、5 行目にあることが記録され、8 行目の先頭にジャンプしnewfuncます。スタックは (概念的に) 次のようになります。

line 5, n=2

13行目に到達すると、新しい関数が再度呼び出され、スタックが作成されます

line 5, n=2; line 13, n=4

スタックが次のようになるまで、これが数回続きます。

line 5, n=2; line 13, n=4; line 13, n=8; line 13, n=16; line 13, n=32; line 13, n=64

if が失敗しnewfunc、スタックをポップして戻り、13 行目以降に実行を再開するとき (これがスタックから取得したものであるため) スタックを作成する

line 5, n=2; line 13, n=4; line 13, n=8; line 13, n=16; line 13, n=32

スタックprintf

line 5, n=2; line 13, n=4; line 13, n=8; line 13, n=16;

など、コール スタック全体を巻き戻します。

いくつかの最終的な詳細: スタックは概念的に「上に」成長するため、しばしば次のように記述します。

line 13, n=32
line 13, n=16
line 13, n=8 
line 13, n=4 
line 5, n=2 

スタックの内容の正確な形式は、チップのアーキテクチャと、OS プログラマーによって行われたいくつかの決定に依存します。


ところで--acプログラムは通常、「どこに」を示すために行番号を使用しません。これは、cでは行が適切な尺度ではないためです(私が十分に愚かであれば、プログラム全体を1行で書くことができます)、代わりに値を使用しますチップ上のレジスタの一部ですが、ここでの説明にはあまり影響しません。

于 2012-10-29T17:08:39.303 に答える
0

実際に何が起こるかというと、13行目の関数を呼び出すと、その時点で関数を実行できなくなった後のコードがスタックと呼ばれるメモリ内の特別な場所に格納され、下から埋められて新しいコードが上に埋められます。スタックの。したがって、最初の関数呼び出しで、printf("\n%d",2)はスタックの一番下に追加されます。printf("\n%d",4);つまり、2 * n = 2 * 2 = 4が前のスタックの一番上に 追加され、再帰的な実行が停止します。上からスタックプログラムが実行され、単純な分析では予測できない上記の複雑なタイプの出力が生成されます。

于 2012-10-29T17:01:52.293 に答える
0

10などの小さな値を考えてみましょう

1st call from main         ////returned from newfunc(2)
newfunc(2)             
//inside newfunc(2)
print 2
2<10 (correct)
newfunc(4)  --> on stack print 2  //returned from newfunc(4)
-------------------------------
//inside newfunc(4)
print 4 
4<10
newfunc(8)  --> on stack print 4 //returned from newfunc(8)
---------------------------------
//inside newfunc(8)
print 8
8<10
newfunc(16) --> on stack print 8 //returned from newfunc(16)
---------------------------
//inside newfunc(16)
print 16
16<10 failed

そのため、それreturnを呼び出した前の関数に移動する-->ため、この例ではスタックの一番上にあるシンボルに移動し、画面printに表示するために使用されますresult

機能シーケンスは上から下へ... これを図で示してみました。あなたがそれを得る願っています。

here-->ステートメントは下から上に実行されるため、結果は次のようになります

2
4
8
16
8
4
2
于 2012-10-29T17:13:48.110 に答える