Var
A : Array [1..4] of Integer;
B : Array [1..4] of Integer;
Begin
A := B;
ここでローレン・ペクテルが言ったように 、問題は私にとってAとBが異なるユニットにあるということです。では、別のクラスの既存のものから型定義を定義する方法はありますか?
Var
A : Array [1..4] of Integer;
B : Array [1..4] of Integer;
Begin
A := B;
ここでローレン・ペクテルが言ったように 、問題は私にとってAとBが異なるユニットにあるということです。では、別のクラスの既存のものから型定義を定義する方法はありますか?
uses
あるユニットのインターフェイス ブロックで型を定義し、その型が必要な他のユニットに句を介してそのユニットを含めます。
unit A;
interface
type
TMyArray = array [1..4] of Integer;
...
TMyArray
別のユニットで使用する必要がある場合:
unit B;
interface
uses A;
...
var x : TMyArray;
もう 1 つのアプローチは、少し古い方法ですが、まだ機能します。これは、ABSOLUTE キーワードを使用して、一方のメモリを強制的に別のメモリにオーバーレイし、もう一方の型に互換性を持たせることです。たとえば、ユニット a には、次のものがあるとします。
TYPE
TArrayA = Array[1..4] of integer;
次に、ユニット b には、次のものがあります。
TYPE
TArrayB = Array[1..4] of integer;
互換性のために、次のことができます。
VAR
InstanceA : TArrayA;
InstanceB : TArrayB;
InstanceBasA : TArrayA ABSOLUTE InstanceB;
これが行うことは、変数「InstanceB」と同じメモリ空間をオーバーレイするタイプ ArrayA の変数「InstanceBasA」を作成することです。これにより、次のコマンドを実行できます。
InstanceA := InstanceBasA;
Delphi の配列型は少し奇妙です。A と B はまったく同じ型のように見えますが、Delphi はそれらが同じであるとは見なしません。「Array [1..4] of Integer」が 2 回出てくるので、Delphi は 2 つの異なるタイプがあると考えます。それは Delphi の奇妙なところです。他のほとんどの言語は気にしないと思います。実際には問題ありません。少し奇妙です。多分それには正当な理由があります。知るか。他の人が言ったように、解決策は、他のユニットで使用できるユニットに入れることができる独自のタイプを定義することです。混乱を招く可能性があるため、配列型のこの問題について言及します。
インターフェイスの後、実装の前にUnitBで UnitA を使用するだけです ...!!!!
それらを型キャストすることにより、コンパイラーにそれらが同じ型であると想定させることができます。
type
TIntArray = array[1..4] of integer;
begin
Assert(SizeOf(ArrayA) = SizeOf(TIntArray));
Assert(SizeOf(ArrayB) = SizeOf(TIntArray));
TIntArray(ArrayA) := TIntArray(ArrayB);
ただし、両方が実際には array[1..4] であることを確認する必要があります。そうしないと、一部のメモリが上書きされます。そのため、2 つのアサーションを追加しました。
variablea から variableb にデータを移動するもう 1 つの方法は、MOVE コマンドを使用することです。たとえば、ArrayA から ArrayB に移動するには、次のようにします。
var
ArrayA : array[1..4] of Integer;
ArrayB : Array[1..4] of Integer;
begin
FillChar(ArrayB[1],SizeOf(ArrayB),#0);
ArrayA[1] := 1234;
ArrayA[2] := 3456;
ArrayA[3] := 7890;
ArrayA[4] := 9876;
// This is where the move from ArrayA to ArrayB happens.
Move( ArrayA[1], ArrayB[1], SizeOf(ArrayA) );
Assert( ArrayA[4] = ArrayB[4], 'ArrayA[4] <> ArrayB[4]');
end;
これは、配列が線形に配置されているという事実によって機能するため、最初の配列位置から始まる配列の長さのバイトをコピーします。
絶対に、絶対に、絶対に、次のようなコードを使用しないでください。
// This is where the move from ArrayA to ArrayB happens.
Move( ArrayA[1], ArrayB[1], SizeOf(ArrayA) );
欠陥はどこにありますか?DESTINATION サイズではなく、移動するバイト数を取得するために SOURCE サイズを使用しています!!! SizeOf(A) > SizeOf(B) の場合、バッファ オーバーフローが発生し、メモリを上書きしています。運がよければ AV を取得できますが、そうでない場合は、悪用可能な脆弱性があります。常に目的のサイズを使用する方がはるかに優れていますが、この方法では、Size(B) > Size(A) の場合にすべきではないメモリを読み取ってしまう可能性があり、不要なデータが公開される可能性があります。とにかく、データを移動するときは常に構造の境界を確認してください - 一部の企業は、このような操作 (つまり memcpy() ) をコードから禁止しています。