0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

<10> ポインタ型 (標準 Pascal 範囲内での Delphi 入門)〔裏〕

Last updated at Posted at 2021-02-16

10. ポインタ型 (Pointer Types)

10.1. ポインタ変数と動的変数 (対象変数)

(10.1.1.) ポインタ型の宣言

・ポインタ型の宣言 (Modula-2 の場合)

Modula-2 では POINTER TO でポインタ変数を作るようになっています。^ は逆参照演算子として使うので、この記述の方が初学者は混乱しないかもしれません。

Modula-2
TYPE
  T: INTEGER;
  P = POINTER TO T;

10.2. New と Dispose

・クラシック Pascal の Dispose()

動的変数が不要になった場合には Dispose(Ptr) を使って動的変数が使用していた領域を解放します。

クラシック Pascal には Dispose() がありませんでした。

See also:

(10.2.1.) New と Dispose の二番目の書式

・New と Dispose の二番目の書式 (標準 Pascal)

Delphi では可変部を持つレコード型は共用体の代わりくらいにしか使われていないため、「何故レコード型の可変部に case 文に類似した構文が含まれているのか?」というのを理解しづらいと思います。

New と Dispose の二番目の書式は解りにくい機能ですが、要は入れ子になった可変部のあるレコード型を一部に限定して確保するメモリを節約するというものです 1。New(P, C1,..., Cn) を使って作られた動的変数は Dispose(Q, K1,..., Km) で解放する必要があります。

次のような定義があったとします。

type
  a = (a1, a2);
  b = (b1, b2);
  c = (c1, c2);
  rec1 = record
           case tc: c of
             c1: (fc1: Integer);
             c2: ()
         end;
  rec2 = record
           case ta: a of
             a1: (case tb: b of
                    b1: (fb1: rec1);
                    b2: ()
                 );
             a2: ()
         end;
var
  p: ^rec2;                                                 

パラメータが一つの書式を使うと、rec2 は可変部のうちの最大の可変要素サイズでメモリが確保されますが、

  New(p);

二番目の書式を使うと、パラメータで指定した可変要素のサイズでメモリが確保されます。次の例では b1 を格納するためのメモリは確保されません。

  New(p, a1, b2);

二番目以降の実パラメータは可変部の可変要素に使った選択定数を渡します。変数を渡すことはできません。

レコード型の
ポインタ変数
1 段目の
可変要素
2 段目の
可変要素
p a1 b2

次の指定は許されません。b1 は入れ子になった可変部を持っていないからです。

  New(p, a1, b1, c2);

二番目の書式を使って作られた動的変数 p は、rec2 型の変数 r への代入もアクセスもできない事に注意が必要です。

var
  r: rec2;
  p: ^rec2;
begin
  New(p, a1, b2); 
  
  p^ := r; { NG }
  r := p^; { NG }

  Dispose(p, a1, b2); 
end.

この二番目の書式を詳細に解説してある書籍はそれほど多くありません。

(10.3.) @ 演算子

・@ 演算子の由来

Delphi には @ 演算子があります。

この拡張は Apple Lisa Pascal 由来のようです。

Turbo Pascal には Version 4 で導入されています (正確には Turbo Pascal for the Mac から)。

・Addr() 関数

@ 演算子に類似のルーチンとしては Addr() があります。@ 演算子の存在しない、古い Turbo Pascal では Addr() を使ってオブジェクトのアドレスを知る事ができます。

上記コードは Turbo Pascal 3.0 (CP/M) で Hello,world. を表示させるものです。

STRTEST.PAS
program STRTEST;
var
  s: string[20];
begin
  s := 'Hello,world.$';
  Bdos(9, Addr(s[1]));
end.

Delphi での Addr() は常に形なしポインタ (Pointer 型) を返します。{$T+}{$TYPEDADDRESS ON} に影響されません。

See also:

(10.4.) ポインタ定数とグローバルポインタ変数の初期化

(10.5.) Pointer 型

(10.6.) 型チェック済みポインタ

(10.7.) 型キャスト

(10.7.1.) 値 型キャスト

(10.7.2.) 変数 型キャスト

サイズが同じならキャストできるようになったのは、Turbo Pascal 4.0 以降です。それ以前の Turbo Pascal では、byte <-> char のような一部の型しかキャストできませんでした

(10.8.) ポインタ演算 (Pointer Arithmetic)

索引

:ramen: [ ← 9. ファイル型〔裏〕 ] [ ↑ 目次へ ] [ → 11. 手続きと関数〔裏〕 ]

  1. 木の枝をそのまま使うか、枝打ちして一部の枝だけを使うかといった感じです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?