Davidがコメントで指摘したように、POINTERMATH
をサポートしていないと、本当にこのようなことしかできません。
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
TIntArray = array [0..0] of integer;
PIntArray = ^TIntArray;
var
p : PIntArray;
i : integer;
begin
GetMem(p, 5*5*SizeOf(integer));
for i := 0 to 24 do p^[i] := i;
for i := 0 to 24 do
WriteLn(Format('i=%d, value = %d', [i,p^[i]]));
ReadLn;
FreeMem(p);
end.
質問は2D配列についてですが、2Dインデックス作成の動作が必要な場合があります。
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
T2DIntArray = array [0..0, 0..0] of integer;
P2DIntArray = ^T2DIntArray;
var
p2d : P2DIntArray;
i, j : integer;
begin
GetMem(p2d, 5*5*SizeOf(integer));
for i := 0 to 4 do
for j := 0 to 4 do p2d^[i,j] := i*j;
for i := 0 to 4 do
for j := 0 to 4 do
WriteLn(Format('i=%d, j=%d, value = %d', [i,j,p2d^[i,j]]));
ReadLn;
FreeMem(p2d);
end.
しかし、これは無意味な結果をもたらします。コンパイル済みのアセンブリから、それは何が起こっているかを確認するために非常に簡単です:
Project1.dpr.16: for i := 0 to 4 do
0041A522 33C0 xor eax,eax
0041A524 A3CC1E4200 mov [$00421ecc],eax
Project1.dpr.17: for j := 0 to 4 do p2d^[i,j] := i*j;
0041A529 33C0 xor eax,eax
0041A52B A3D01E4200 mov [$00421ed0],eax
0041A530 A1CC1E4200 mov eax,[$00421ecc] // load i into EAX
0041A535 F72DD01E4200 imul dword ptr [$00421ed0]// EAX = i*j
0041A53B 8B15C81E4200 mov edx,[$00421ec8] // load p2d into EDX
0041A541 8B0DCC1E4200 mov ecx,[$00421ecc] // load i into ECX
0041A547 8D148A lea edx,[edx+ecx*4] // offset p2d by i*SizeOf(integer)
0041A54A 8B0DD01E4200 mov ecx,[$00421ed0] // load j into ECX
0041A550 89048A mov [edx+ecx*4],eax // move i*j to EDX + j*sizeOf(integer)
0041A553 FF05D01E4200 inc dword ptr [$00421ed0]
0041A559 833DD01E420005 cmp dword ptr [$00421ed0],$05
0041A560 75CE jnz $0041a530
0041A562 FF05CC1E4200 inc dword ptr [$00421ecc]
だから、明確に、これは働いていない - コンパイラは、インデックス
を終わるように、単位の大きさを持っている最初の次元を期待します0、1、2、3、4、
1、2、3、4、5、
2、3、4、5、6、
...等
ヨーヨー場合定義を
type
T2DIntArray = array [0..4, 0..4] of integer;
P2DIntArray = ^T2DIntArray;
に変更すると、すべて正常に動作します。
Project1.dpr.16: for i := 0 to 4 do
0041A522 33C0 xor eax,eax
0041A524 A3CC1E4200 mov [$00421ecc],eax
Project1.dpr.17: for j := 0 to 4 do p2d^[i,j] := i*j;
0041A529 33C0 xor eax,eax
0041A52B A3D01E4200 mov [$00421ed0],eax
0041A530 A1CC1E4200 mov eax,[$00421ecc]
0041A535 8D0480 lea eax,[eax+eax*4] // this is more like it
0041A538 8B15C81E4200 mov edx,[$00421ec8]
0041A53E 8D0482 lea eax,[edx+eax*4] // and this..
0041A541 8B15D01E4200 mov edx,[$00421ed0]
0041A547 8B0DCC1E4200 mov ecx,[$00421ecc]
0041A54D 0FAF0DD01E4200 imul ecx,[$00421ed0]
0041A554 890C90 mov [eax+edx*4],ecx // so we get what we want
0041A557 FF05D01E4200 inc dword ptr [$00421ed0]
0041A55D 833DD01E420005 cmp dword ptr [$00421ed0],$05
0041A564 75CA jnz $0041a530
0041A566 FF05CC1E4200 inc dword ptr [$00421ecc]
しかし、当然、これはひどく柔軟ではありません。コンパイル時に型の固定境界を定義する必要があります。これはあまり満足のいくものではありません。コンパイラは、実行時にインデックスを正しく計算できるように、十分に定義された次元サイズの型定義が必要です。したがって、一般的な場合には、多次元の動作を手動で実装する必要があります(線形インデックス変換を使用)。
これは、デルファイでは賢明な方法ではありません。私はこれが学校の課題だと理解していますが、CプログラマのようにDelphiコースを教えるような感じです。このようなやり方でこの種のことをしたいのであれば、Delphiは本当に適切なものではないと思います。 Delphiの新しいバージョンでは、より柔軟な(POINTERMATH
)がありますが、このスタイルのプログラミングのユースケースは非常に限られていると考えられます。
2D配列についてはお話ししますが、試行された逆参照では1つのインデックスしか表示されません。配列にインデックスを付けるには、いくつかの方法があります。細部が提供されずに何が最善であるかを知ることは難しい。これは宿題のようですが、あなたの仕事を詳細に話したことはありません。あなたはあなたの家庭教師に尋ねましたか? –
@DevidHeffernanはい、それは大学での仕事です。 2D配列を作成し、getmemを使用して入力するだけです。私はそれがここにあったようにしようとしましたhttp://stackoverflow.com/questions/32957977/using-getmem-for-allocation-of-multidimensional-arrays – mobimore
私はあなたがタスクのより詳細な説明を持っていると思っているでしょうか私たちよりも?次に何が起こるかは、私たちが何かを提案し、あなたが「ああ、私の仕事は私にそれをさせてくれません」と言うことです。それは私たちにとって楽しいものではありません。なぜあなたは自分の宿題をしませんか?あなたはこれをする方法を教えられた授業に行っていませんでしたか?あなたのテキストブックは何を言いますか?なぜあなたはポインタを配列として扱うことができると思いましたか?それは授業で教えられましたか?あなたは家庭教師に相談しましたか? –