ポインタ参照


ハムハム  2008-11-27 18:44:59  No: 32727

好き嫌いの類かもしれませんが・・・

type
  TPtrHogeHoge=^THogeHoge;
  THogeHoge=Record
    Hoge1:Integer;
    Hoge2:Integer;
  end;

上記の宣言のとき、下記の関数のようにポインタで使用する場合
下記の(1)と(2)、どちらで記述しますか?

procedure aaa(PHoge: Pointer);
begin
  //(1)
  THogeHoge(PHoge^).Hoge1
  //(2)
  TPtrHogeHoge(PHoge)^.Hoge1
end;

TPtrHogeHogeの宣言が、あってもなくても、(1)なら通用します。
でも、この宣言がなければ、ローカルに宣言したり、
  pHoge: ^THogeHoge
のように、変数を宣言して使うことになるでしょう。

そういった点を見ると、(1)は便利な記述になるのですが、
単なるPointer型を逆参照(でいいの?)すると、その型って何?
型無しのなにか?
それをキャストしてもいいの?
と、なんか、違和感があるんですよね。
それに、(2)よりもコストがかかりそうなイメージが・・・。

質問というよりアンケートみたいなものなので、興味があればレスください。
また、速度面で説明できる人がいたら、ぜひ解説をお願いしたいです。


ハムハム  2008-11-27 18:45:57  No: 32728

一応、現環境は、Delphi5 です。


monaa  2008-11-27 23:20:26  No: 32729

気になったら実際に時間を測定してみたらどうですか?
私は機械語を読むことはできないので、気になった時は時間を測ってます。
今回の場合は、ほぼ同じ値なのでマシン語レベルは同じだと思われます。

type
  PHoge=^THoge;
  THoge=Record
    int:Integer;
  end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i:Integer;
  c:Cardinal;
  p:Pointer;
begin
  c:=GetTickCount;
  new(p);
  THoge(p^).int:=0;
  for i := 0 to 100000000 do
    //inc(THoge(p^).int);
    inc(PHoge(p)^.int);
  Caption:=IntToStr(GetTickCount-c);
end;


monaa  2008-11-27 23:28:15  No: 32730

いあ、違う…
↑では動きません。
p:Pointerではなくp:pHogeなら同じになります。
new(p)のときにpのメモリサイズを確保してるんですね。
気づきませんでした。


monaa  2008-11-27 23:33:20  No: 32731

new(PHoge(p));
はできるけど
new(^THoge(p));
はできないのでどのみちPHoge=^THoge;は必要そうです。


そうね  2008-11-27 23:54:08  No: 32732

>単なるPointer型を逆参照(でいいの?)すると、その型って何?
>型無しのなにか?
>それをキャストしてもいいの?
この解釈は間違ってる。
THogeHoge(PHoge^).Hoge1
このように書くと、PHogeは型無しポインタではなく、TPtrHogeHoge型のポインタになる。
そうでなければコンパイルが通らない。
TPointer型は、すべてのポインタ型との代入互換性があるけど、型キャストせずに直接逆参照はできないということ。
TPtrHogeHoge=^THogeHoge;
このような宣言が必要なのは、引数として構造体のポインタ変数を
要求するWinAPIが多いからで、ポインタ変数が不要であるならば
キャストで済ませばいいと思う。
>THogeHoge(PHoge^).Hoge1
>TPtrHogeHoge(PHoge)^.Hoge1
CPUウィンドウを見れば、この二つは同じマシン語に変換されると
分かるんじゃないかな?


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加