|
■No91927 (えんえん さん) に返信 > それでも、やはり正しい結果は得られないのですが、なぜでしょうか?
「ar と ai」「tmpr と tmpi」は、再帰処理のたびに入れ替わりますよね。 ざっと見た感じでは、入れ替えた際の添字管理に問題があるように見えます。
話を単純化するため、元の処理を下記のように置き換えてみましょう。
void Proc(int x[], int y[]) { if (x[0] != 0) Proc(&y[1], x); } void main() { int ar1[4] = { 11, 22, 33, 0 }; int ar2[4] = { 55, 66, 77, 0 }; Proc(ar1, ar2); }
この場合、ポインタは以下のように遷移しますよね。 この動作をポインタ代わりの r_st% で管理しようとして、失敗しているように見えます。
main から渡す実引数は ar1 が { 11, 22, 33, 0 } ar2 が { 55, 66, 77, 0 } → C++ の main から呼び出された Proc の仮引数 x は { 11, 22, 33, 0 } y は { 55, 66, 77, 0 } →→→ 1 回目の再帰処理で呼ばれた Proc の仮引数 x は { 66, 77, 0 } y は { 11, 22, 33, 0 } →→→→ 2 回目の再帰処理で呼ばれた Proc の仮引数 x は { 22, 33, 0 } y は { 66, 77, 0 } →→→→→ 3 回目の再帰処理で呼ばれた Proc の仮引数 x は { 77, 0 } y は { 22, 33, 0 } →→→→→→ 4 回目の再帰処理で呼ばれた Proc の仮引数 x は { 33, 0 } y は { 77, 0 } →→→→→→→ 5 回目の再帰処理で呼ばれた Proc の仮引数 x は { 0 } y は { 33, 0 } ←←←←←← 再帰が終わって呼び出し元(4 回目)に戻る x は { 33, 0 } y は { 77, 0 } ←←←←← 再帰が終わって呼び出し元(3 回目)に戻る x は { 77, 0 } y は { 22, 33, 0 } ←←←← 再帰が終わって呼び出し元(2 回目)に戻る x は { 22, 33, 0 } y は { 66, 77, 0 } ←←← 再帰が終わって呼び出し元(1 回目)に戻る x は { 66, 77, 0 } y は { 11, 22, 33, 0 } ←← 再帰が終わって最初の呼び出しに戻る x は { 11, 22, 33, 0 } y は { 55, 66, 77, 0 } ← C++ の main まで戻ってきて ar1 が { 11, 22, 33, 0 } ar2 が { 55, 66, 77, 0 }
> 配列はByValやByRefを指定しなくとも > 参照型(ByRef)で渡されることは知っていますが
いろいろごちゃ混ぜになっているような。
ByVal / ByRef の省略の話と、配列であるかどうかは無関係ですし、 ByVal / ByRef の話と 値型 / 参照型 の話も別物ですよ。
> 後から、コードを見たときに分かりやすくするために > 一応、付けています。
『値渡し』を望むなら、ByVal は省略しようと明示しようと、どちらでも構わないと思います。 自分の場合、新規開発ならば省略表記にした方がスッキリするので記述しませんが、 VBA からの移行であれば、明示的に記述して移植時の意図を明確にするようにしています。
一方、『参照渡し』を望むなら、VBA とは違って、ByRef を明示する必要があります。 しかし ByRef を付けた理由が「配列だから」というのなら、使い方が間違っています。
> ちなみに、普通は配列にはByValやByRefを付けないものなのでしょうか? 配列かどうかは一切関係ありません。
使い分けの方針としては、「出力引数」として実装する場合に限って ByRef を使い、 それ以外の場合は全て、値渡しとして処理させるのが普通です。
ただ、出力引数を使うことがそもそも稀であるため、.NET Framework のライブラリで見ても、 ByRef が利用されているものは殆どありません。使うとしても TryParse メソッドぐらいのものでしょう。
|