ab.com コミュニティ

ActiveBasicを通したコミュニケーション
現在時刻 - 2024年4月24日(水) 20:07

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




新しいトピックを投稿する  トピックへ返信する  [ 12 件の記事 ] 
作成者 メッセージ
 記事の件名: 配列の引渡し
投稿記事Posted: 2005年9月26日(月) 16:51 
コード:
#strict

Dim a[1,1]=[[1,2],[3,4]] As Byte
dim lpa As VoidPtr
lpa=VarPtr(a)
Z(a)
End

Sub Z(ByVal a[1,1] As Byte)
	dim lpa As VoidPtr
	dim a0 As byte
	lpa=VarPtr(a)
	debug
	a0=a[0,1] ←アクセス違反
End Sub
上記プログラムをコンパイルした時点で
[警告] "Z"の第1パラメータが、*ByteからByteに強制変換されています。
となります

実行するとZ内のlpaはa[0,0]の値が返ります
  • a配列(&H12FFBC)
    [0,0]16
    [0,1]0
    [1,0]0
    [1,1]0
    lpa 16
    a0 0
グローバル値は
  • a配列(&H407010)
    [0,0]1
    [0,1]2
    [1,0]3
    [1,1]4
    lpa 4222992(&H407010)


通報する
ページトップ
   
 記事の件名: 追記
投稿記事Posted: 2005年9月26日(月) 17:00 
AB4.10.00です

前のVERSION(4.04)に戻しても同様になってしまいました

4.10にする前の4.04では、Z内のA配列の値は同様ですが
動作的には問題なしです


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年9月27日(火) 01:07 
オフライン

登録日時: 2005年8月23日(火) 00:15
記事: 161
お住まい: 沖縄県
どのような処理を行いたいのか分かりませんが・・・
普通の処理言語では、値渡しで配列全体の内容や配列の形状を送る事はできません。
もし、引数のa[0,1]と同じ値を参照するプログラムを作ると
コード:
#strict

Dim a[1,1]=[[1,2],[3,4]] As Byte
Z(a)
End

Sub Z(a As BytePtr)
    dim a0 as byte
    a0=a[0*2+1]      'この計算式が重要
End Sub
動作の説明
ローカル変数で参照するのは、関数Zを呼び出すさいにセットしたグローバル変数のアドレスです。
指定した配列を元に計算を行ったアドレスが存在しない場合は、もちろんエラーで落ちます。(運が良ければ動作したりします)
先頭のアドレスしか渡せないので、配列の格納位置計算は自分でします。

実はABには特別な仕様があって、構造を含めた関数コールが可能であったら教えて下さい。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2005年9月27日(火) 14:03 
オフライン

登録日時: 2005年5月31日(火) 17:59
記事: 899
お住まい: 東京都
> 実はABには特別な仕様があって、構造を含めた関数コールが可能であったら教えて下さい。
Hさんのコード自体がそうです。
http://www.discoversoft.net/help_center ... ameter.htm
ここの「多次元配列をパラメータとして引き渡すには」に書いてあります。

Hさんのコードではグローバル変数とZの引数のaをLongなどにすればアクセス違反は発生しませんでした。
ほか、16/32bit整数型では全て問題ありませんでしたが、Charと浮動小数点型はだめでした。
64bit整数型は元のZでは問題ありませんでしたが、そこへa[0, 0]~a[1, 1]を画面へ出力するようにしたところ、
画面に出力が見えた直後にアクセス違反で落ちてしまいました。

ちなみにアクセス違反が起きない際にはlpa = VarPtr(a[0, 0])とすればグローバル変数の値とZのローカル変数の値は一致します。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2005年9月28日(水) 23:23 
返信ありがとうございます

説明不足でした
Z関数内でのa配列の参照ポインタの場所が違うのではとの疑問だったのですが・・・
(上記コードは検証用に作成したものです)

イグトランスさんにならって、再度検証したところ
   デバッグ時のlpaの値 → 続行クリック
    (ローカル)
8bit:&H78 → アクセス違反
16bit:&H5678 → アクセス違反
32bit:&H12345678 → 正常終了
64bit:&H12345678 → 正常終了*1
*1 ただし64bit型ではENDをはずすと、アクセス違反が発生します
*2 lpaのグローバル値は&H12345678です
*3 ヘルプセンターのサンプルプログラムでも検証しようとしたのですが
  うまくいきませんでした(デバッグでストール状態)

なお、現在配列の仮引数はByValになっていますが
ByRefの方がわかりやすいと思うのですがいかがでしょう

以上、調査および検討をお願いします


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年9月29日(木) 23:37 
オフライン

登録日時: 2005年8月23日(火) 00:15
記事: 161
お住まい: 沖縄県
イグトランスさんありがとうございます。非常に勉強になりました。

ところで、パラメータの参照方法に、引数が値参照(By Value)を指定すると配列、構造体を値参照することはできません。
とありますので、今回の回答は、ByRefを指定して下さいが正解でしょうか?


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2005年9月30日(金) 20:27 
オフライン

登録日時: 2005年5月31日(火) 17:59
記事: 899
お住まい: 東京都
> とありますので、今回の回答は、ByRefを指定して下さいが正解でしょうか?
それがそうでもないのです。やってみるとわかりますが、
「配列ポインタを引渡すときは、値参照(ByVal)にしてください」
というエラーになります。
つまり配列をByRefではなく配列へのポインタをByValでという考えになっているようです。
前に示したURLでも全てByVal/ByRefの指定を省略しているのでByVal扱いとなっていますね。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2005年9月30日(金) 23:21 
オフライン

登録日時: 2005年8月23日(火) 00:15
記事: 161
お住まい: 沖縄県
すみません!現象を理解できないので
これはABのコンパイラエラーメッセージのバグではなく、仕様と言うことでしょうか?
配列や、構造体を値渡し(ByVal)するようなことは、絶対にはありえないと思います。(というか実装できるのですか?)
山本様
値渡しで構造体や配列を渡す事は不可能(勝手な推測)なので正しい仕様をお教え下さい。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2005年10月01日(土) 09:25 
オフライン

登録日時: 2005年5月31日(火) 17:59
記事: 899
お住まい: 東京都
> 配列や、構造体を値渡し(ByVal)するようなことは、絶対にはありえないと思います。(というか実装できるのですか?)
> 山本様
> 値渡しで構造体や配列を渡す事は不可能(勝手な推測)なので正しい仕様をお教え下さい。

 私はもちろん山本様ではありませんが、勝手ながら書かせてもらいます。

 あれは構文上配列をByValとなっていますが、実際にはポインタをByVal渡しするようです。
前に示したURLのページにも次のようなことが書かれてあります。
引用:
この引き渡し方法は、具体的には配列のポインタのみを引き渡しています。
 ところでC/C++では構造体・クラスを値渡しで引数、戻り値に指定できます。(引数に構造体・クラスの値渡しは推奨されていませんが)
配列では値渡しだと引数の場合にはポインタに読み替えられ、戻り値にはできません。(参照渡しはCになくC++で導入されたので配列の参照渡しはできますがほとんど使われていません)
 ABが配列をByValと指定するのはこの「引数の型を配列の値渡しと指定するとポインタの値渡しにコンパイラが読み替える」というC/C++の仕様を模倣したためと私は思っています。

 たしかにABの配列をByVal指定する仕様はいまいち馴染まないような感じがします。
しかしながらByValを明示して書くからそう感じるだけで、省略してしまえば大して気にならないとも思っています。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2005年10月01日(土) 11:38 
オフライン

登録日時: 2005年8月23日(火) 00:15
記事: 161
お住まい: 沖縄県
イグトランスさんの説明で理解しました。
大昔に、オブジェクト仕様を習った際、関数を準備する側が全ての変数に対応できるようにする義務があるような話だったので、
C++系は全く勉強していませんでした。

ついでに原因も分かりましたので報告します。
コード:
Dim a[1,1]=[[1,2],[3,4]] As Byte
配列をこの形で初期化すると、だめなようです!
プログラムでデータを設定すると大丈夫でした。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2005年10月02日(日) 17:44 
> ついでに原因も分かりましたので報告します。
>
コード:
> Dim a[1,1]=[[1,2],[3,4]] As Byte
> 
> 配列をこの形で初期化すると、だめなようです!
> プログラムでデータを設定すると大丈夫でした。


相変わらずうまくいかないです
やはり、ポインタ参照位置おかしくないですか?

配列の初期化については、こちらをみてください


通報する
ページトップ
   
 記事の件名:
投稿記事Posted: 2005年10月03日(月) 13:31 
オフライン

登録日時: 2005年8月23日(火) 00:15
記事: 161
お住まい: 沖縄県
私の勘違いでした!!!ABのバグのようです!

Hさんlpaの考察通り、関数に配列のアドレスを渡せないのが原因でした!
引用:
8bit -> アドレスの下位1バイトのみ転送
16bit -> アドレスの下位2バイトのみ転送
32bit -> アドレスが全て渡るのでOK
となっていました!

山本様
配列渡しや構造体渡しは、ByRef型にした方が良いとおもいませんか?
#strict
を強化する際の障害になって行くような気がします。

PS.私の実験結果はたまたま動いていたみたいです。


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

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


オンラインデータ

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


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

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