Edited at

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


10. ポインタ型 (Pointer Types)

これまでに説明されてきた型はいずれも静的に割り当てられる静的変数でした。動的変数 (対象変数)動的に作れる変数です。


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

動的変数 (対象変数)そのものは変数宣言部に現れることはなく、名前がないため直接アクセスすることはできません。

その代わりに宣言済み手続き New()Dispose() を使って生成と削除を行い、ポインタ値 (割り当てられた動的変数のアドレス) によって識別を行います。このため、ポインタ値はその型に適合するポインタ型の変数に代入する必要があります。

ポインタ型 = 

 ^ 型名.

例えば文字型 Char に対するポインタ型は次のように定義できます。

type

TPChar = ^Char;

次のようにポインタ型 (文字ポインタ型) の定義と変数の宣言を同時に行うこともできます。

var

P: ^Char;

ポインタ型 Ptr があるとき、動的変数そのものは Ptr^ で表します。これはポインタの逆参照となります。

See also:


10.2. New と Dispose

動的変数を作成してそのポインタ値を Ptr に代入するには New(Ptr) を使います。動的変数が不要になった場合には Dispose(Ptr) を使って動的変数が使用していた領域を解放します 1 。この時、Ptr の値は不定となります。

手続き
説明

New()
新しい動的変数を作成し、パラメータに渡された
ポインタ変数を動的変数のポインタに設定する。

Dispose()
動的変数用に割り当てられたメモリを解放する。


PointerTest1.pas

program PointerTest1(output); 

type
TPChar = ^Char;
var
Ptr: TPChar;
C: Char;
begin
New(Ptr); { 動的変数の領域を確保し、ポインタ値を Ptr に設定 }

Ptr^ := 'A';
C := Ptr^;

Dispose(Ptr); { 動的変数の領域を解放 }
Ptr := nil;

Writeln(C);
end.


ポインタ型には動的変数が割り当てられていないことを示す予約語 nil を代入しておく事ができます。nil は任意のポインタに代入できる特殊な定数です。 nil をポインタに代入すると、そのポインタは何も参照しません。


(10.3.) @ 演算子

Delphi には @ 演算子があります 2 。これは変数のポインタ値を参照する演算子です。変数 T のポインタ値は @T で参照できます。


PointerTest2.pas

program PointerTest2(output); 

type
TPChar = ^Char;
var
Ptr: TPChar;
C: Char;
begin
C := 'A'; // 変数 C に 'A' を代入
Ptr := @C; // 変数 C を指すポインタを Ptr に代入
Ptr^ := 'B'; // Ptr を逆参照した先 (C) に 'B' を代入
Writeln(C); // 'B' が表示される
end.

See also:


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

Delphi では次のようなポインタ定数が使えます。


PointerTypeConstantsTest.pas

program PointerTypeConstantsTest;

{$APPTYPE CONSOLE}

// グローバル変数
var
I: Integer = 0;

// グローバルポインタ定数
const
PInt1: ^Integer = @I;

// グローバルポインタ変数と初期化
var
PInt2: ^Integer = @I;

procedure Sub;
// ローカル配列変数は初期化できない
//var
// PInt3: ^Integer = @I;
begin
...
end; { Sub }
begin
...
end.


使い所が難しいと思います。

See also:


(10.5.) Pointer 型

Delphi には型情報のないポインタ型 (void ポインタ) である Pointer という宣言済みのポインタ型があります。このポインタ型は型情報が関連付けられていないため逆参照できません。


PointerTest4.pas

program PointerTest4(output);

type
TPChar = ^Char;
var
P: Pointer;
C: Char;
begin
New(TPChar(P)); { 動的変数の領域を確保し、ポインタ値を P に設定 }

//P^ := 'A'; // NG
TPChar(P)^ := 'A'; // OK
C := TPChar(P)^;

Dispose(TPChar(P)); { 動的変数の領域を解放 }
P := nil;

Writeln(C);
end.


型付きのポインタ型にキャストして逆参照する事は可能です。

See also:


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

@ 演算子が返すポインタ型は {$T} コンパイラ指令によって変化します。デフォルトの {$T-} の状態では @ 演算子の結果の型は常に他のすべてのポインタ型と互換性のある型なしポインタ (Pointer 型) になります。{$T+} の状態で @ が変数参照に適用される場合、変数 T に適用された結果の型は ^T になります。ここで、T は、その変数の型へのポインタとしか互換性がありません。

var

PI: PInteger;
PD: ^Double;
I: Integer;
begin
PI := @I;
PD := @I; // {$T+} だとコンパイルエラーになる
end.

See also:


(10.7.) 型キャスト

先述のように、Delphi では型キャストを行えます。型キャストとはある式を別の型の式であるかのように扱えるようにする機能です。

See also:


(10.7.1.) 値 型キャスト

値型キャストでは、型識別子とキャスト式の両方が、順序型またはポインタ型でなければなりません。

Integer('A')

Char(48)
Boolean(0)
Integer(@Buffer)


(10.7.2.) 変数 型キャスト

変数は、サイズが同じであり、整数と実数を混在させない限り、任意の型にキャストすることができます。

Char(I)

Boolean(Count)
TSomeDefinedType(MyVariable)


索引

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





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



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