[リストへもどる]   [VBレスキュー(花ちゃん)]
一括表示

投稿時間:2006/03/01(Wed) 15:34
投稿者名:つぼちゃん
Eメール:
URL :
タイトル:
バイト指定のString型変数での出来事
VB6です。

以下のようなプログラムで、func1関数で"bbb"と書き換えたstr1が、
Command1_Clickに戻ると書き換える前の値"aaa"に戻ってしまいます。

str1 を Dim str1 As String と宣言するか、
Call func1(str1) を Call func1(trim(str1))
とすると、str1はCommand1_Clickに戻ってきても書き換えた"bbb"となります。

これはどういうことでしょうか。

Option Explicit

Dim str1 As String * 10

Private Sub Command1_Click()
    
    str1 = "aaa"
    
    Call func1(str1)
    
    MsgBox "func1から戻った後のstr1は" & str1
    
End Sub

Private Function func1(str2 As String) As Boolean
    str1 = "bbb"
    
    MsgBox "func1でのstr1は" & str1
    
    func1 = True
    
End Function

投稿時間:2006/03/01(Wed) 17:34
投稿者名:魔界の仮面弁士
Eメール:
URL :
タイトル:
Re: バイト指定のString型変数での出来事
それは、やっちゃいけないコーディングの一つだったりします…。
# 理由としては、ISBN4-89100-455-X の 411 頁あたり
## VB.NET か VB6 かで、多少動作が変わってくるけれど。


>    Call func1(str1)
VB6 の仕様上、引数に固定長文字列型は使えませんよね。可変長文字列型のみです。

そのため、String 型引数に String * ? 型の変数を渡すと、その変換のために
メモリ上に『一時的な変数のコピー』が用意され、それが渡される事になります。

しかも ByRef の場合は、プロシージャ側で変更された引数の内容が、
「変数に書き戻される」という作業が発生するため、今回の問題を引き起こします。


> Private Function func1(str2 As String) As Boolean
今回、この str2 には、モジュールレベル変数 str1 を渡していましたので、
func1 に入った直後では、それぞれの変数は
 モジュール変数 str1 = "aaa       "
 引数 str2 = "aaa       "
という状態になっています。ここまでは良いですよね。


>     str1 = "bbb"
そしてこの時点で、モジュール変数 str1 は "bbb       " になりますね。
では、str2 の値はどうなっているでしょうか?

ByRef の引数なので、通常であれば str2 は str1 の別名として扱われ、
両者共に "aaa       " に置き換わるはずなのですが、今回は
「一時的な変数のコピー」が渡されているため、それぞれ別の変数として処理され、
  モジュール変数 str1 は "bbb       "
  引数 str2 は "aaa       "
という状態をひきおこします。


>     MsgBox "func1でのstr1は" & str1
>     func1 = True
> End Function
そのため、ここで問題がおきます。引数 str2 は「ByRef」として扱われていましたので、
このプロシージャを抜けた時点で、引数 str2 の内容が、str1 に書き戻されます。
そのため、func1 を呼び出した後では、str1 = "aaa       " となるわけです。

投稿時間:2006/03/01(Wed) 18:14
投稿者名:つぼちゃん
Eメール:
URL :
タイトル:
Re^2: バイト指定のString型変数での出来事
> それは、やっちゃいけないコーディングの一つだったりします…。
> # 理由としては、ISBN4-89100-455-X の 411 頁あたり
> ## VB.NET か VB6 かで、多少動作が変わってくるけれど。

魔界の仮面弁士さん、大変わかりやすい説明ありがとうございました。