5

特定の配列のすべての項目が同じかどうかを比較する必要があります。

今のところ、次のコードがあります。

Type
  TD = array [0..1] of TDateTime;

var A: TD;
    B: TD;
begin
  A[0] := Date-1;   A[1] := Date+1;
  B[0] := Date-1;   B[1] := Date+1;

  if CompareMem(@A, @B, SizeOf(TD)) then
    Showmessage('Equals')
  else
    Showmessage('Differ');

これは正常に動作していますが、CompareMem はアセンブリで記述されているため、(まだ)何をするのか理解できません。

CompareMem は、私がやりたいことを行うための有効な方法ですか? また、文字列、整数などのすべてのデータ型で機能するかどうかを知りたい.

4

2 に答える 2

5

これはアセンブリで書かれていません...メモリの比較は、すべてのメモリが隙間なく配列項目で満たされている場合に有効です。通常、次の場合に機能します

1) すべての配列メモリは、ギャップなしでデータで満たされます (ギャップにはゴミが含まれており、偽陰性を引き起こす可能性があります)。

1.1。packed arrayコンパイラがそれを無視しない場合、これはキーワードで強制する必要があります

1.2 これは、SizeOf(A[1]) が 2,4,8,16 などの場合に発生するはずです。

ただし、さまざまなパターンで FillChar を使用した単体テストでこれをカバーすることをお勧めします。それらはガベージを模倣し、配列要素に一致する値を手動で入力し、要素が事前に入力されたガベージをすべて消去したことを CompareMem で確認します。

2) 配列要素には、参照型ではなく、単純な値型のみが含まれます。

Char、integer、double、short string、固定サイズの配列、またはそれらで作成されたレコードは単純型です。

他のすべての文字列、ポインター、オブジェクト、インターフェイス、動的およびオープン配列は、外部データへの単なるポインターであり、「メモリによって」比較することはできません。

詳細なヒントについては、http://docwiki.embarcadero.com/Libraries/XE2/en/System.Finalizeを参照してください。さまざまな Delphi データ型のバイナリ表現をカバーするため、プロシージャ/関数のアセンブラ実装も良いトピックです。

于 2013-06-18T17:37:06.303 に答える
5

CompareMem単純にバイトごとの比較を実行します。CompareMem値による等価テストで有効にならない主な原因は 2 つあります。

  1. テスト中の型にはパディングが含まれています。
  2. テストされている型は、参照型であるか、参照型を含んでいます。

配列について質問しています。配列は常に pack されるため、パディングは含まれません。配列の値を比較しているので、質問は配列の要素に集中できます。

配列の値の比較は、配列要素がパディング バイトを含まず、参照型を含まない値型である場合にのみ、適切に実行できます。

これは、すべての単純な値の型に当てはまります。

レコードの場合、レコードに参照型が含まれているかどうかを確認する必要があります。これは再帰チェックでなければなりません。レコードには、参照型などを含むレコードが含まれていますか。そして、パディングを探す必要があります。パディングを見つけるとすぐに、の使用はCompareMem適切ではありません。

于 2013-06-19T06:51:31.523 に答える