[ポインタ]

型変換ではありませんが、ポインタについて2つのサンプルを示します。

・ポインタの示すアドレス、中身を表示させます。
・文字列をポインタを使って置き換えます。


◆ポインタについて

通常の変数は、値そのものを格納しますが、メモリ上のアドレスを格納することのできる特別な変数を、ポインタと呼びます。

◆ポインタ変数の宣言 
 宣言方法は2種類あります。どちらを使ってもかまいません
・型名の前に「^」(キャレット)を付けて、変数を宣言する
 例)var c:^Char; b:^Byte; i:^Integer; d:^Double; 
・型名にPを付けて、変数宣言する
 例)var c:PChar; b:PByte; i:PInteger; d:PDouble; 
◆ポインタの使用
.櫂ぅ鵐進竸名のみ記述する 例)P
 →ポインタ変数に格納されているアドレスの示す、「データ自身」を指します。
  データ自身が「ヌルで終わる文字列」の場合、#0(ヌル)までが処理対象になります
  下図の'abcd'を指します
∧竸名をIntegerでキャストする 例)integer(P)
 →変数が配置されている、メモリ上のアドレスを示します
  用途はほとんどありませんが、変数がメモリ上のどこに配置されているか見ることができます。試してみて!
  下図の△裡組崔呂鮖悗靴泙
J竸名の前に「@」(アットマーク)を付ける 例)@P
 →ポインタ変数に格納されているアドレスを示します。
  「データ自身」がメモリ上のどこに格納されているか見ることが出来ます。
  下図ののデータアドレスのB番地を指します 
ぅ櫂ぅ鵐進竸名の後ろに「^」(キャレット)を付ける 例)P^
 →ポインタ変数の示すアドレスの中身の1バイトを示します。
  下図のぁ韮瓠任裡吋丱ぅ箸鮖悗靴泙
図:ポインタ変数はデータのアドレスをポイントしています
     ポインタ変数            データ 
 A番地[データのアドレス]−−−>  B番地[ 'abcd' ]
  ◆    ´               ↓'a'のみ
ポインタの示すアドレス、中身を表示させます。
【ソースコード】 [tips0013.pas]
program tips0013;
{$APPTYPE CONSOLE}
uses SysUtils;
var
 a:string;
 b:PChar;
 c:PChar;
begin
 a:='abc';
 b:=PChar(a);
 WriteLn('◆string変数');
 WriteLn('a<変数>のアドレスは       :',IntToHex(Integer(@a),6));   //@aをIntegerにキャスト
 WriteLn('a<変数>の指すアドレスは       :',IntToHex(Integer(a),6));    //aをIntegerにキャスト
 WriteLn('a<変数>の中身は         :',a); 

 WriteLn('◆PChar変数');
 WriteLn('b(ポインタ)のアドレスは     :',IntToHex(Integer(@b),6));   //@bをIntegerにキャスト
 WriteLn('b(ポインタ)の指すアドレスは   :',IntToHex(Integer(b),6));    //bをIntegerにキャスト
 WriteLn('b(ポインタ)の指すアドレスの中身は:',b);
 WriteLn('b(ポインタ)の逆参照の中身は   :',b^);

 WriteLn('◆PChar変数 メモリ確保');
 GetMem(c,Length(a));
 StrCopy(c,PChar(a));
 WriteLn('c(ポインタ)のアドレスは     :',IntToHex(Integer(@c),6));   //@bをIntegerにキャスト
 WriteLn('c(ポインタ)の指すアドレスは   :',IntToHex(Integer(c),6));    //bをIntegerにキャスト
 WriteLn('c(ポインタ)の指すアドレスの中身は:',c);
 WriteLn('c(ポインタ)の逆参照の中身は   :',c^);
 FreeMem(c); 

end.
【コンパイル&実行】 [tips0013.bat]
dcc32 tips0013.pas 
tips0013.exe  > tips0013.txt
pause
【実行結果】 [tips0013.txt]
◆string変数
a<変数>のアドレスは       :411D8C
a<変数>の指すアドレスは       :A06AA4
a<変数>の中身は         :abc
◆PChar変数
b(ポインタ)のアドレスは     :411D90
b(ポインタ)の指すアドレスは   :A06AA4
b(ポインタ)の指すアドレスの中身は:abc
b(ポインタ)の逆参照の中身は   :a
◆PChar変数 メモリ確保
c(ポインタ)のアドレスは     :411D94
c(ポインタ)の指すアドレスは   :A0D9D0
c(ポインタ)の指すアドレスの中身は:abc
c(ポインタ)の逆参照の中身は   :a
◆ポインタ以外の変数についての注意事項
上記の結果から、string変数も内部的にはポインタの構造になっています。
ポインタとデータの関係を図にしてみました。
     変数aのポインタ          データ 
 A番地[データのアドレス]−−−>  B番地[ 'abc' ]
 411D8C  A06AA4          A06AA4  

     ポインタb             データ 
 A番地[データのアドレス]−−−>  B番地[ 'abc' ]
 411D90  A06AA4          A06AA4  

     ポインタc             データ 
 A番地[データのアドレス]−−−>  B番地[ 'abc' ]
 411D94  A0D9D0          A0D9D0  
ポインタbにstring変数aのアドレスをセットするには下記の2つの方法が考えられます。
  b:=PChar(a);    //PCharでキャストする方法
  b:=@a;          //@を付ける方法
2つの結果は異なりますので注意が必要です。
 PCharでキャストする方法: データ部分のアドレス(上記の図のB番地:A06AA4)が格納されます。
 @を付ける方法     : ポインタではない変数aは、内部的にはポインタの構造になっています。
              変数aのポインタ部(上記の図のA番地:411D8C)が格納されます。


文字列をポインタを使って置き換えます。
【ソースコード】 [tips0013_2.pas]
//小文字のaを大文字Aに置き換える。小文字bを大文字BBBBBに置き換える
program tips0013_2;
{$APPTYPE CONSOLE}
uses SysUtils;
var
 S,R  :string;
 Sp,Rp:PChar;  //Char型のポインタ定義
begin
 S:='abcabc&amss&lco&gen';
 R:='                         ';

 Sp:=PChar(S);  //変数SをPCharでキャスト(型変換)して、変数Sのアドレスをポインターに代入する
 Rp:=PChar(R);  //変数RをPCharでキャスト(型変換)して、変数Rのアドレスをポインターに代入する

 while Sp^ <> #0 do //変数Sの末尾を検出するまでループする #0はnull
  begin
   case Sp^ of  //変数Sのポインタの示す内容を調べる
    'a':        //'a'ならば大文字の'A'を変数Rにセットする
      Rp^:='A'; 
    'b':        //'b'ならば5バイトの'BBBBB'を変数Rにセットし、変数Rのポインタをインクリメント(+4)する
     begin
      StrCopy(Rp,'BBBBB');
      inc(Rp,4);
     end;
    else
     Rp^ := Sp^;  //上記以外の文字ならば、変数Sから変数Rへ1バイトコピーする
   end;
   inc(Sp);  //変数Sのポインタをインクリメント(+1)する
   inc(Rp);  //変数Rのポインタをインクリメント(+1)する
  end;

 WriteLn(S); //変数Sを出力する
 WriteLn(R); //変数Rを出力する

end.

【コンパイル&実行】 [tips0013_2.bat]
dcc32 tips0013_2.pas 
tips0013_2.exe  > tips0013_2.txt
pause
【実行結果】 [tips0013_2.txt]
abcabc&<>
ABBBBBcABBBBBc&<>