hinekure.net が http://hspdev-wiki.net/ から自動クローリングした結果を表示しています。画像やリソースなどのリンクが切れています。予めご了承ください。
小ワザ/ポインタを使ってのあれこれ - HSP開発wiki
トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS

小ワザ

hsp3.png

ポインタを使ってのあれこれ

はじめに

プログラム言語でいうところのポインタとは、一般的にはある目的のために確保されているメモリ領域のアドレスを示す値です。
普通にHSPでプログラムを行う際には意識する必要はないものですが、ポインタを介してHSPのシステム内部にアクセスすることにより標準の命令だけではできない処理を行うことが可能になります。

メモリ領域の状態はプログラムの動作に伴い常に変わりつづけるので、さっき有効だったポインタが今も有効であるという保証はありません。
ポインタの取得はポインタを使った処理の直前に行うようにするべきです。

変数・配列変数とポインタ

変数に関するポインタ

PVal構造体

HSP3 の変数に関する情報はシステムの管理する PVal構造体の中に格納されています。PVal構造体は変数一つにつき一つずつ存在します。
スクリプトから PVal構造体に直接アクセスすることはできませんが、PVal構造体へのポインタ(PValポインタ)を取得することにより間接的にアクセス可能になります。

配列変数の場合でも PVal構造体は変数一つにつき一つです。配列の要素ごとに存在するわけではありません。
ただし配列変数では配列内の特定の要素を指定するために APTR値を使用します。
配列変数のある要素に対する APTR値はその配列変数のの全次元の全要素を一直線に並べたときのその要素の先頭からの位置となります。

HSPスクリプトでの PValポインタの取得(pvalptr)

PValポインタ(PVal構造体へのポインタ)をスクリプトから直接取得するための命令は用意されていませんが、間接的に取得する方法はあります。

  • input 命令で作成された入力ボックスのオブジェクト情報から取得
  • #deffunc(#defcfunc) のユーザー定義命令(関数)の引数情報から取得
 

上記の手法を使って PValポインタを取得するための pvalptr 関数のモジュールです。

+  モジュールスクリプト

PValポインタを使ってのPVal構造体へのアクセス

dupptr 命令を使い PVal構造体のクローンを配列変数として作成し、その配列変数にアクセスします。
ただし、その内容を書き換えた場合は HSP の動作が不安定になる可能性がありますので注意してください。
HSP3 の PVal構造体のサイズは48バイトですので

dupptr (変数名), (PValポインタ), 48, 4

とします。(変数(0)から変数(11)までのint型配列変数になります)

サンプルスクリプト : PVal構造体を使った各種変数情報の取得

サンプルスクリプト 1 : 標準命令で取得できるものと同じ情報をPVal構造体から取得する。
+  サンプルスクリプト 1
サンプルスクリプト 2 : 標準命令では取得できない情報をPVal構造体から取得するための関数。

モジュール mod_pval.hsp では PVal構造体から情報を取得するための次の関数が定義されています。

  • varclone 関数
    変数がクローン変数なのか実体のある変数なのかを調べます。
  • bufsize 関数
    変数用に現在確保されているバッファサイズを取得します。

これらの関数を使ったサンプルスクリプトです。

+  サンプルスクリプト 2

ユーザー定義命令(関数)の引数とポインタ

#deffunc, #defcfunc で定義されるユーザー定義命令・関数の引数に関するポインタ

ユーザー定義命令(関数)の引数

プログラム中でユーザー定義命令(関数)が呼び出されると、引数の内容に関する情報がシステムの管理する引数スタック領域( HSPCTX::prmstack )に格納されます。
型ごとの詳細は次の通りです。

  • int型、double型の引数
    引数スタック領域に実引数の値そのものが格納されます。(int型 4バイト、double型 8バイト)
  • str型の引数
    メモリにバッファ領域が確保され、実引数の内容がそこにコピーされます。
    引数スタック領域にはそのバッファ領域へのポインタが格納されます。(4バイト)
  • var型、array型の引数
    引数スタック領域に実引数の PValポインタ値、APTR値が格納されます。(8バイト)
  • local 引数
    引数スタック領域に PVal 構造体が格納されます (48バイト)。
  • modvar 引数 ( thismod )

    #modfunc, #modcfunc の第一引数には、モジュール変数を管理する MPModVarData? 構造体(12byte)が積まれます。これは、PVal ポインタ値と APTR 値の他に、モジュール変数の種類も積まれています。

  • modinit, modterm 引数

    #modinit, #modterm の第一引数も、#modfunc などと同じです。

引数スタック領域に代入された内容、str型のバッファ領域の双方とも一時的なもので、ユーザー定義命令(関数)の処理が終了すると( return で戻ると )無効になります。

ユーザー定義命令(関数)の引数へのポインタ

前述の事柄よりユーザー定義命令(関数)の引数へのポインタは、引数スタック領域内の該当する個所へのポインタということになります。
具体的には命令(関数)が呼び出された直後の HSPCTX 構造体の prmstack メンバの値から算出します。

HSPCTX.prmstack                               = 引数 1 に関する情報
HSPCTX.prmstack + 引数 1 に関する情報のサイズ = 引数 2 に関する情報
HSPCTX.prmstack + 引数 2 に関する情報のサイズ = 引数 3 に関する情報
               ...
サンプルスクリプト : ユーザー定義命令の引数にポインタを使ってアクセス

ポインタを使って引数にアクセスするサンプルです。

+  サンプルスクリプト

PVal構造体とSTRBUF構造体の関係

PVal構造体はひとつの変数につき一つの構造体で管理していますが、配列変数の要素など、変数の実体はSTRBUF構造体で要素ごとに管理されていることがあります。
特に可変長データである文字列配列を管理するのに、文字列そのものを連続した領域内( 配列 )で管理するのは都合が悪いです。
そこで文字列の実体は各々別の場所に確保し、PVal構造体は様々な場所に散らばったひとつ変数で参照される文字列を、文字列へのポインタ配列で管理することで、多次元文字列配列を実現しています。
この配列はPVal構造体の master メンバにより参照され、実際には文字列配列ではなく文字列へのポインタ配列となります。

以上をまとめると、変数の実体を管理するのはSTRBUF構造体で、STRBUF構造体を管理しているのがPVal構造体であるといえます。

+  文字列配列のマスターテーブル

コメント

  • mod_pvalptrを使った文字列多次元配列のテキスト保存作ってみました。パラメータのチェックはしていません。PVal構造体のmasterポインタを参照していますが、どうせなら先頭要素へのポインタもmasterテーブルに載せてくれると、先頭要素を特別扱いせずに済むのにな...あと、サポート外の"%s"使ってます。サポート外なのにエラーを出さずにヌルチェックというのは...^^; -- kz3 2006-05-10 (水) 13:24:31
  • と言っても仕方ないので自分で先頭インデックスに書き込むようにしました。 -- kz3 2006-05-10 (水) 13:27:43
  • strf はサポート外の "%s" が動作しているのではなくて、第2引数が文字列だとその文字列をそのまま返すようです。 -- naznyark? 2006-05-11 (木) 02:22:29
    Everything is expanded.Everything is shortened.
      1
      2
      3
      4
      5
      6
      7
      8
    
     
     
     
     
     
     
     
     
    
        i = 9999 : s = "abc"
        mes strf("i : %d", i)
    ;   mes strf("i : %s", i)	;	これはエラー
        mes strf("s : %d", s)
        mes strf("s : %s", s)
        mes strf(" : %d", "123")
        mes strf(" : %s", "123")
        mes strf("","123")    ;	これなんかいい加減^^;<kz3
    
  • そうなんですよね。 -- kz3 2006-05-11 (木) 08:43:11
  • モジュールmod_pvalptrはポインタだけでなくpvalのあらゆる情報を取得できるのでmod_pvalって端折ってもいいかなと思ったりです^^が、getpval命令でp1がarrayになってますが、これはvarでもいいですよね? -- kz3 2006-05-11 (木) 16:37:32
  • > モジュールmod_pvalptrはポインタだけでなくpvalのあらゆる情報を取得できるのでmod_pvalって端折ってもいいかなと思ったりです
    それもそうですね。というわけで名前変更しました。
    > getpval命令でp1がarrayになってますが、これはvarでもいいですよね?
    varでもいいです。でも動作が異なる場合があるのでどっちがいいかな(悩)・・・? -- naznyark? 2006-05-12 (金) 02:48:59
    (参考)varとarrayの違い。配列の先頭要素以外の要素を渡して型変換を伴う処理が行われる場合。
    Everything is expanded.Everything is shortened.
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
    
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    
    #module
    #deffunc test_v var _p1
        _p1=100, 200 : return
    #deffunc test_a array _p1
        _p1=100, 200 : return
    #global
        s="ab", "cd" : test_v s(0)
        mes ""+s(0)+","+s(1)
        s="ab", "cd" : test_a s(0)
        mes ""+s(0)+","+s(1)
        s="ab", "cd" : ;test_v s(1);	エラー。
        mes ""+s(0)+","+s(1)
        s="ab", "cd" : test_a s(1)
        mes ""+s(0)+","+s(1)
  • こういう使い分けはどうかな? -- kz3
    Everything is expanded.Everything is shortened.
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
    
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    
    #module
    #deffunc _dimv var p1, int p2
        mes p1
        dim p1, p2
        return
    #deffunc _dima array p1, int p2
        mes p1
        dim p1, p2    
        return
    #global
        hoge   = 3 : _dimv hoge, 10
        hoge.2 = 33: _dimv hoge.2, 10 ; 内容の破棄を警告してくれる
     
        piyo   = 5 : _dima piyo, 10
        piyo.4 = 55: _dima piyo.4, 10 ; 内容の破棄を警告してくれない
        piyo.0 = 66: _dima piyo.4, 10
  • あ、arrayだと要素を渡しても渡されるのは常に先頭?みたいですね。 -- kz3 2006-05-12 (金) 06:08:44
  • モジュールリストにpvalモジュールへリンク追加しておきました。ページ名、pvalほにゃららに変えたほうがいいでしょうか? -- kz3 2006-05-19 (金) 10:01:14
  • お手数かけます。ページ名は今のままでいいと思いますよ。 -- naznyark? 2006-05-20 (土) 01:45:16
  • おっけいですー。 -- kz3 2006-05-20 (土) 10:16:36
  • arrayは配列渡し、varは変数要素渡しです。
    だから var でとったものは配列として使えない。 -- 2009-11-21 (土) 14:49:51

URL B I U SIZE Black Maroon Green Olive Navy Purple Teal Gray Silver Red Lime Yellow Blue Fuchsia Aqua White

添付ファイル:
filesample_prmptr.hsp
400件 [詳細]
filesample_mod_pval_2.hsp
482件 [詳細]
filesample_mod_pval_1.hsp
458件 [詳細]
filemod_pval.hsp
585件 [詳細]
トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS
Last-modified: 2009-11-21 (土) 14:49:51 (1478d)