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)数组元素只包含简单的值类型,不包含引用类型。

字符、整数、双精度、短字符串、固定大小的数组或由这些组成的记录 - 都是简单类型。

所有其他字符串、指针、对象、接口、动态和开放数组——只是指向外部数据的指针,不能“按内存”进行比较

您可以阅读http://docwiki.embarcadero.com/Libraries/XE2/en/System.Finalize以获得更多提示。程序/函数的汇编器实现也是一个很好的话题,因为它涵盖了不同 Delphi 数据类型的二进制表示

于 2013-06-18T17:37:06.303 回答
5

CompareMem只需执行逐字节比较。有两种主要方式CompareMem无法通过值进行相等性测试:

  1. 被测试的类型包含填充。
  2. 被测试的类型是或包含引用类型。

你在问数组。由于数组总是被打包的,它们不包含填充。由于您正在比较数组值,因此问题可以集中在数组的元素上。

当且仅当数组元素是不包含填充字节且不包含引用类型的值类型时,数组的值比较才是合适的做法。

这是所有简单值类型的情况。

对于记录,您需要检查记录是否包含引用类型。这必须是递归检查。记录是否包含包含引用类型的记录,等等。然后你必须寻找填充。一旦发现padding,使用CompareMem就不合适了。

于 2013-06-19T06:51:31.523 回答