▼ マスター、Novさん
色々と説明して頂き恐縮です。
何度も読み返したのですが、私の頭では理解できません。
それで、以下のコードを試してみました。
それぞれのポイントでの変数の内容と変数のアドレスを
表示するようにしただけです。
type
TTestAry = array of integer;
procedure ABC(var buf:TTestAry);
var
i,len,count:integer;
s:string;
begin
s := 'ABC手続 buf ' + IntToHex(Integer(buf),8);
Form1.listbox1.Items.Append(s);
s := 'ABC手続 @buf ' + IntToHex(Integer(@buf),8);
Form1.listbox1.Items.Append(s);
len := Length(buf); // 今のサイズを得る
count := 0;
// 100〜200のデータをbufにセットする処理
for i := 100 to 200 do begin
buf[count] := i;
inc(count);
// 配列の数を増やす ---------
if count >= len then begin
len := len + 10; // とりあえず10増やす
SetLength(buf,len);
s := 'SetLength' + inttostr(len) + ' buf ' + IntToHex(Integer(buf),8);
Form1.listbox1.Items.Append(s);
s := 'SetLength' + inttostr(len) + ' @buf ' + IntToHex(Integer(@buf),8);
Form1.listbox1.Items.Append(s);
end;
// --------------------------
end;
// 配列の数を実際の数に揃える
SetLength(buf,count);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Abuf:TTestAry;
i,len:integer;
s:string;
begin
// 動的配列設定
SetLength(Abuf,10); // とりあえず10確保
s := 'Button1手続 SetLength Abuf ' + IntToHex(Integer(Abuf),8);
Form1.listbox1.Items.Append(s);
s := 'Button1手続 SetLength @Abuf ' + IntToHex(Integer(@Abuf),8);
Form1.listbox1.Items.Append(s);
// 手続きを呼び出す
ABC(Abuf);
s := '戻った Abuf ' + IntToHex(Integer(Abuf),8);
Form1.listbox1.Items.Append(s);
s := '戻った @Abuf ' + IntToHex(Integer(@Abuf),8);
Form1.listbox1.Items.Append(s);
// 結果の表示
len := Length(Abuf);
for i := 0 to len - 1 do begin
ListBox1.Items.Append(inttostr(Abuf[i]));
end;
end;
その結果、@Abuf、@bufともに常に同じアドレスを示していました。多分、
procedure TForm1.Button1Click(Sender: TObject); で定義した
var
Abuf:TTestAry; ← のアドレスだと思います。
Abuf、bufは時々変化していました。
Abuf、bufは動的配列の先頭位置のアドレスを示している筈です。
Novさんが言われている通りSetLengthすると時々アドレスが変わっています。
多分、確保したメモリー空間で収まらなくなったので、別の広いメモリー空間に
移動した?のではないかと想像しています。
いや、そういう問題じゃなくてトラブルのもとになるようなコードを
書くべきじゃないとマスターは言われているのだと思いますが、とりあえず
この結果でこの件は自分としては納得しました。
今作成中のプログラムも「varなし」の方法に書き換えていきます。
こんな事にマスターを巻き込んでしまいスミマセンでした。
|