以前、ユーザ定義関数の値渡し・参照渡しについて記事にしましたが、 抜けていた項目もありますので、再度紹介します。
ユーザ定義関数を作成する場合に、何がしかの引数(ひきすう)を持つことはよくあります。 この引数の渡し方には、値渡し(call by value)と、 参照渡し(call by reference)の2種類があります。
値渡しとは、引数で渡された値を関数内では参照・変更できるが 呼出し元の変数に影響を与えない。
参照渡しとは、引数で渡された値を関数内で変更した場合、 呼出し元の変数に影響を与えます。 言い方を変えれば、関数内で参照する変数は、 呼出し元の変数を直接アクセスしています。 C言語的に言えば、参照つまり変数のポインタを引数で渡すことでしょうか。
よく関数は独立性を持たせるために、値渡しが推奨されますが、 参照渡しには参照渡しの良さもあります。 値渡しの値そのものは関数を呼出す時に、ユーザ定義関数用スタックに格納されます。 (スタックなので積むと表現した方がしっくりきますが)
渡される値が文字列で非常に長い場合などは、スタックの消費が多くなりますし、 値そのものをスタックにコピーされる時間が多くかかります。 これを抑えるために参照渡しにすることがあります。
また、配列データを引数で渡す時には値渡しではできなく、 参照渡しにしなければなりません。 配列データは多くのメモリ領域を必要とするため、 BHT-BASICではメモリもそんなに多くないので、 参照渡しの仕様にしたのだと思います。
以下のソースがその例なのですが以下の4個の関数を宣言しています。 ・TestByval の名前で値渡し関数
・TestByref の名前で参照渡し関数
・TestByval2%% の名前で値渡し値を返す関数
・TestArrByref の名前で配列・参照渡し関数
このソースの実行の様子は以下の様になります。(最初のキー入力待ちまでの表示)
値渡しの関数ではWK%が変更されないことが確認できます。 また、参照渡しの関数ではWK%が変更さたことが確認できます。
その後、配列データの変更がされたことを確認する表示が以下の様になります。
=====
2016/04/02:の時の情報
ユーザ定義関数を作成する場合に、何がしかの引数(ひきすう)を持つことはよくあります。 この引数の渡し方には、値渡し(call by value)と、 参照渡し(call by reference)の2種類があります。
値渡しとは、引数で渡された値を関数内では参照・変更できるが 呼出し元の変数に影響を与えない。
参照渡しとは、引数で渡された値を関数内で変更した場合、 呼出し元の変数に影響を与えます。 言い方を変えれば、関数内で参照する変数は、 呼出し元の変数を直接アクセスしています。 C言語的に言えば、参照つまり変数のポインタを引数で渡すことでしょうか。
よく関数は独立性を持たせるために、値渡しが推奨されますが、 参照渡しには参照渡しの良さもあります。 値渡しの値そのものは関数を呼出す時に、ユーザ定義関数用スタックに格納されます。 (スタックなので積むと表現した方がしっくりきますが)
渡される値が文字列で非常に長い場合などは、スタックの消費が多くなりますし、 値そのものをスタックにコピーされる時間が多くかかります。 これを抑えるために参照渡しにすることがあります。
また、配列データを引数で渡す時には値渡しではできなく、 参照渡しにしなければなりません。 配列データは多くのメモリ領域を必要とするため、 BHT-BASICではメモリもそんなに多くないので、 参照渡しの仕様にしたのだと思います。
以下のソースがその例なのですが以下の4個の関数を宣言しています。 ・TestByval の名前で値渡し関数
・TestByref の名前で参照渡し関数
・TestByval2%% の名前で値渡し値を返す関数
・TestArrByref の名前で配列・参照渡し関数
'File [MODULE1.SRC]
'値渡し関数テスト
Sub TestByval(byval pintWK%)
pintWK% = pintWK% + 1 '引数の変数を変更できる
PRINT "pintWK%="; pintWK% '変更確認
End Sub
'参照渡し関数テスト
Sub TestByref(byref pintWK%)
pintWK% = pintWK% + 1 '引数の変数を変更できる
PRINT "pintWK%="; pintWK% '
End Sub
'値渡し関数テスト2
Function TestByval2%(byval pintWK%)
pintWK% = pintWK% + 1
TestByval2% = pintWK% '戻り値で引数変数値を返す
End Function
'配列参照渡し関数テスト
Sub TestArrByref(byref pintArrWK%())
PRIVATE I%
FOR I% = 1 TO 4
PRINT "pintArrWK%("; I%; ")="; pintArrWK%(I%)
'配列データに1加算
pintArrWK%(I%) = pintArrWK%(I%) + 1
NEXT I%
End Sub
'-----
'実行はここから処理
'-----
Main
SCREEN 1 '漢字モード
LOCATE , , 2 'カーソルをブロック表示
PRIVATE WK%
WK% = 1
'値渡しの関数コール
PRINT "値渡しの関数..."
Call TestByval(WK%)
PRINT "WK%="; WK%
'参照渡しの関数コール
PRINT "参照渡しの関数..."
Call TestByref(WK%)
PRINT "WK%="; WK%
'値渡しの関数2コール
PRINT "値渡しの関数2..."
WK% = TestByval2%(WK%)
PRINT "WK%="; WK%
'配列を渡すテスト
PRIVATE I%, ArrWK%(4)
FOR I% = 1 TO 4
ArrWK%(I%) = I% * 10
NEXT I%
Call TestArrByref(ArrWK%)
PRIVATE W$
WAIT 0, &h01 'キー入力待ち
W$ =Input$(1) '入力されたキーを取得して戻す。
PRINT "TestArrByrefコール後"
FOR I% = 1 TO 4
PRINT "ArrWK%("; I%; ")="; ArrWK%(I%)
NEXT I%
WAIT 0, &h01 'キー入力待ち
END
このソースの実行の様子は以下の様になります。(最初のキー入力待ちまでの表示)
値渡しの関数ではWK%が変更されないことが確認できます。 また、参照渡しの関数ではWK%が変更さたことが確認できます。
その後、配列データの変更がされたことを確認する表示が以下の様になります。
=====
2016/04/02:の時の情報
PR
コメント