Delphiでポインタ


 ポインタってナニ?


簡単に言えば、「矢印」です。場所を示すための矢印。
コンピュータでは、メモリの位置(アドレス)を示すものをポインタと呼びます。

ポインタは変数ではありません。これが大事なことです。しかし、変数のように扱うことも出来ます。
インラインアセンブラでは、大きなデータには配列でアクセスすることはなく、全てポインタを使って行います。

 変数


変数は、ご存知の通り、

var i:Integer;
j:Byte;

等のものです。

変数は、指定された型(Integer型,Byte型等)を超える大きさを与えることが出来ません。自由にサイズや長さを変える事は出来ません。これは、既に形を完全に固めてしまっているためです。

たとえば、自由に柔軟な大きさを作りたいという要求があるはずです。たとえば、ファイルの読み込みでサイズがどのような大きさになるか、実際に読み込まないと分からない、という場合です。

このようなとき、実体が無いポインタを使うことになります。
ポインタを指定して、サイズをメモリ確保、ポインタの示すメモリ領域をアクセスして使用し終わったらメモリ開放、という手順を踏みます。

 ポインタの宣言


変数の型のように、既にポインタの型が決められているものがあります。
PByteArray 8ビット境界(Byte)のポインタ配列。
PWORDArray 16ビット境界(WORD)のポインタ配列
PChar 8ビット境界(Char)のポインタ配列
PInteger 32ビットのポインタ

また、自由にポインタを作ることも出来ます。
var pIn:^Integer;
^Integer=PIntegerです。
変数や構造体に頭に^を付ける事で、ポインタであると設定することが出来ます。
クラス(クラス=構造体+変数+関数+…)は、ポインタの考えは考慮しないので良いのでここでは考えません。

 ポインタの移動と値の取得


ポインタは位置であるというように説明しました。
たとえば、ポインタXが配列Aを示しているとします。

A[0] A[1] A[2] A[3] A[4]

Xに配列Aの一番最初の0番をポインタに指定する場合は、
X=@A[0];
とします。@はポインタ指定の命令です。

A[0] A[1] A[2] A[3] A[4]

X:=X+1;(inc(x))すると、

A[0] A[1] A[2] A[3] A[4]

Xの値は、A[1]となります。
もちろん、X:=X+2すると

A[0] A[1] A[2] A[3] A[4]

Xを引けば、同じように戻ります。
ちなみに、移動幅は1バイト(8bit)ですので、もし、A[x]の大きさが16ビットや32ビットだったりすると、移動幅は2バイト(16bit)や4バイト(32bit)にしなくてはいけません。この辺は、インラインアセンブラを使ってるときに関係してきます。

では、配列型のポインタを実際に使ってみましょう。
var A,B:PByteArray;
GetMEM(A,3200);//0〜3200-1までメモリ確保。

これで、Aはメモリ確保されていますので、普通の配列のように扱うことが出来ます。

ここで、
B:=A;
として、
B[199]:=10;
とした場合、Aはどうなるのでしょうか?
実は、B[199]:=10をしたことは、A[199]:=10したのと同じ事(等価)となります。
あくまでも、A,Bは、変数ではなく、ポインター(位置を示すもの)であって、そのデータ本体ではないからです。
一見、AはBと関係無いように見えますが、B:=A;をしている瞬間から、BはAと全く同じモノであるのです。

画像データを白黒化する例をポインタを使って書いて、このコーナーを終わりにします。
var BMP:TBitmap;
pbit:PByteArray;
x,y,all:Integer;
r,g,b:Byte;

begin

BMP:=TBitmap.Create;
BMP.LoadFromFile('なんじゃら!.BMP');
BMP.PixelFormat:=pf24bit;

for y:=0 to BMP.Height-1 do begin
  pbit:=BMP.Scanline[y];//ポインタをコピーしています。
  for x:=0 to BMP.Width-1 do begin
    r:=pbit[x*3];//ポインタから8ビットのデータを読み込む
    g:=pbit[x*3+1];
    b:=pbit[x*3+2];

    
    all:=(r+g+b) div 3;//平均値を出す
    
    pBit[x*3]:=all;//ポインタに書き込む。
    pBit[x*3+1]:=all;
    pBit[x*3+2]:=all;

  end;
end;

BMP.SaveToFile('おわった.BMP');

BMP.Free;

end;


Copyright(C)'2003- buin2gou
無断でこのページを転載・複写・掲載することを禁じます。