ab.com コミュニティ

ActiveBasicを通したコミュニケーション
現在時刻 - 2024年3月29日(金) 02:45

全ての表示時間は UTC+09:00 です




新しいトピックを投稿する  トピックへ返信する  [ 5 件の記事 ] 
作成者 メッセージ
投稿記事Posted: 2006年9月20日(水) 18:44 
こんにちは。

プログラミング掲示板にするか迷いましたが、こちらに。よく理解しているか分からない者の報告ですが、今回は ByRef と BytePtr の関数についてです。


Sub TestByRef(ByRef ByteLine As BytePtr)

End Sub ...①


Dim lpCommandLine As BytePtr
Dim lpCommandLine2 As BytePtr
Dim W32FD As WIN32_FIND_DATA
Dim lpW32FD As *WIN32_FIND_DATA

lpW32FD = VarPtr(W32FD)
ZeroMemory(lpW32FD, SizeOf(WIN32_FIND_DATA))


lpCommandLine2 = VarPtr(lpCommandLine[数字])
TestByRef(lpCommandLine2) ...②


TestByRef(VarPtr(lpCommandLine[数字])) ...③


lpCommandLine2 = lpW32FD->cFileName
TestByRef(lpCommandLine2) ...④


TestByRef(lpW32FD->cFileName) ...⑤


lpCommandLine2 = VarPtr(W32FD.cFileName)
TestByRef(lpCommandLine2) ...⑥


TestByRef(VarPtr(W32FD.cFileName)) ...⑦


TestByRef(VarPtr(W32FD.cFileName[数字])) ...⑧



②、④、⑥ は問題ありませんが、③、⑦、⑧ は「無効な識別子です」と出、⑤ は型が違いますと出ます。① を Function にしても同様です。

③、⑤、⑦、⑧ が通らないは如何なのでしょうか。


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2006年9月20日(水) 19:37 
オフライン

登録日時: 2005年7月25日(月) 13:27
記事: 893
お住まい: 埼玉県東松山市
3番8番の「数字」と書かれている部分にはその文字列が記入されているのでしょうか?0等の数値が記入されていれば3は大丈夫のはずです。

7番8番はVarPtr関数の戻り値をTestByRef関数に渡しているようですが、ByRefでは基本的に即値(Constで定義された物や数値)や返り値を直に入れることは出来ません。
呼び出し側でByValを指定してやればうまくいきます。

又、ByRefを指定して参照型がBytePtrと言うのは、(特別な場合を除けば)初心者はまず使わない組み合わせですが、どう理解していますか?
ByRefを指定すると、関数にデータが入ってきた後にその値を変更すると、関数を抜けた後にも影響が出ます。
影響を出さないためには何も書かないか(この場合、呼び出し元なら呼び出し先の指示に従い、関数の定義ならByValと同じ。)、ByValを指定してください。
BytePtr型はポインタなので、BytePtr型の参照先を変更すると、関数を抜けた後にも参照先に影響が出ます。
影響を出さないためには、calloc+memcpy等の組み合わせを使って関数内で独自に使用する配列を作成する、などの方法があります。

5番は、cFileNameは[255] As Byteで定義されているはずなので、バグかもしれません。(知識不足なので、イグトランスsあたりにフォロー入れてもらえれば幸いです。)


特別な場合、と説明文中に書きましたが、例えば256バイトの配列を自動で確保してくれるような関数を作った場合に、
コード:
Sub AutoAlloc(ByRef pointer As BytePtr)
    pointer=calloc(256)
End Sub
等と記述する事があります。

_________________
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。


通報する
ページトップ
投稿記事Posted: 2006年9月20日(水) 20:25 
オフライン

登録日時: 2005年5月31日(火) 10:52
記事: 264
お住まい: 高知
引用:
> こんにちは。
こんにちは
引用:
> プログラミング掲示板にするか迷いましたが、こちらに。よく理解しているか分からない者の報告ですが、今回は ByRef と BytePtr の関数についてです。
よく分からない段階では「質問掲示板」の方がいいかもしれませんね。
誰か他にも問題に気付いている方が居られれば、確実にバグと判断できますし、
バグでないならないで解決法を載せられますから。



さて本題です。
コード:
Sub TestByRef(ByRef ByteLine As BytePtr)
End Sub
この関数の引数を見ると「ポインタ変数へのアドレス参照」となっていることがわかりますね。
即ち、この関数は関数内でポインタ変数内に格納されたアドレスを書き換えることができる状態になります。
これを踏まえて以後のプログラムを見てみると問題解決に繋がるのではないかとおもいます。


まず③ですが、これは単純に引数がポインタ参照なのにアドレス値を指定しているというミスです。
アドレス値はあくまで値参照扱いです。
コード:
                    TestByRef(VarPtr(lpCommandLine[数字]))  ...③
次に⑤です。
これはパッと見問題が無いように思えますが、少し考えてみると③と同じミスです。
配列の添え字を省略すると確かに配列の先頭のアドレス値が返りますが、
これは先に述べたようにByRefのポインタ参照ではなくByVal参照が必要です。
コード:
                    TestByRef(lpW32FD->cFileName)  ...⑤
因みにByRef参照をByVal参照に一時変換できる方法がありますので
そちらを使うと③も⑤もエラーはでません
コード:
                    TestByRef(ByVal VarPtr(lpCommandLine[数字]))
                    TestByRef(ByVal lpW32FD->cFileName)

続いて⑦⑧ですがこれも③⑤と同じミスです。
VarPtrでアドレス値をByRefのポインタ参照に渡したい場合はByValを使います。
コード:
                    TestByRef(VarPtr(W32FD.cFileName)) ...⑦
                    TestByRef(VarPtr(W32FD.cFileName[数字])) ...⑧
修正すると下になります。
コード:
                    TestByRef(ByVal VarPtr(W32FD.cFileName))
                    TestByRef(ByVal VarPtr(W32FD.cFileName[数字]))

関数の引数に指定するByValとByRefの違いは慣れていないと結構勘違いし易いです。
2つには使い方にかなり違いがありますし、ポインタ型と組み合わせるとさらに面倒です。
コード:
/* 値参照を使った引数 */
/* もっとも基本的な引数 */
Sub Proc1(x As Long)
End Sub


/* ポインタ参照を使った引数 */
/* ポインタを意識しなくて良い所が便利 */
Sub Proc2(ByRef x As Long)
End Sub


/* 値参照とポインタ型を組み合わせて使った引数 */
/* 配列操作や文字列操作なんかに便利 */
Sub Proc3(x As *Long)
End Sub


/* ポインタ参照とポインタ型を組み合わせて使った引数 */
/* 滅多に使わないというより、使えるような用例が見当たりません */
Sub Proc4(ByRef x As *Long)
End Sub


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2006年9月21日(木) 08:55 
konisi さん、NoWest さん、お早う御座います。

昨晩、御二方の御返信を確認し(返信の時間は有りませんでした)、一時間程考え、問題の部分は理解出来たと思っています。

説明のため、御二方纏めての返信とさせて頂きます。

先ず、3番8番の「数字」と書かれている部分には 0 ~ 9、十六進数では A ~ F も含めて示される数値が入ります。分かり辛い説明で申し訳有りませんでした。

私がしていたのは、konisi さんが特別な場合と説明されているものの、もう少し複雑な感じなもので、プロシージャ内で文字列を繰り返し確保し、それをメインルーチンで使用する様なものです。文字列がポインタで、仮引数のポインタと、実引数のポインタは同じで有って欲しく、且つ長くなる事も有り、ポインタ参照の方で処理しようと思い、やってみました。上手く行かなかった何箇所かを除けば、狙い通りに出来ています。だから、値参照でなくとも出来る筈だと思い込み、自分の理解不足に気付かず、この報告となったという事です。

文字列等に対するポインタ参照と値参照に関しては、以前マティさんから説明を頂いて居りますので、それなりには理解出来ている筈だとは思っています。呼び出し側、もしくは、プロシージャで ByVal を指定すれば、エラーが出ないかもという事は分かっていましたが、初心者なりの意欲も有り、ポインタ参照で解決出来ればと考えました。

「引数がポインタ参照なのにアドレス値を指定している」というのと、(検索が下手なのか出て来ませんが)以前プログラミング質問板で見たと思う、確かイグトランスさんの言葉だったと思いますが、「ポインタというのは32ビット値なんです」みたいなのとが符合し、はっきり理解出来たと思っています。

此処まで読むと、確かにプログラミング質問板。今後は、よく分からない段階では向こうへ載せる事にします。今回は、ご容赦を。

有難う御座いました。


通報する
ページトップ
   
 記事の件名: 申し訳在りません。
投稿記事Posted: 2006年9月21日(木) 08:59 
上は彦左衛門の投稿です。名前入れ忘れました。


通報する
ページトップ
   
期間内表示:  ソート  
新しいトピックを投稿する  トピックへ返信する  [ 5 件の記事 ] 

全ての表示時間は UTC+09:00 です


オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[8人]


トピック投稿:  可
返信投稿:  可
記事編集: 不可
記事削除: 不可
ファイル添付: 不可

検索:
ページ移動:  
Powered by phpBB® Forum Software © phpBB Limited
Japanese translation principally by ocean