2013-06-18 128 views
4

我需要比较给定数组的所有项是否相同。CompareMem适合比较两个数组是否相等?

现在,我有以下代码:

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是一种有效的方式来做我想做的事吗?另外,我想知道,如果将工作的每一个数据类型,如字符串,整数等

+3

使用CompareMem只能使用简单的数据类型。如果数据是托管类型的,比如对象,字符串,动态数组等,那么您只是比较指针值。 –

+0

一般答案是** no **,因为数组元素可能[align](http://docwiki.embarcadero.com/RADStudio/XE4/en/Align_fields_%28Delphi%29)。然而,如果你打算永远留在Borland编译器和Intel架构中,你可以安全地做到这一点(这是因为Borland阵列隐式地被封装)。 – OnTheFly

回答

4

这不是用汇编...比较存储器是有效的,如果所有的记忆充满了数组项无间隙。一般来说,如果

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。的过程/函数汇编实现也将是很好的话题,因为它会覆盖不同德尔福数据类型

+0

这不是装配? – EProgrammerNotFound

+0

你的第二个代码是程序集,但是你谈到你最初引用的代码是Pascal。那么,CompareMem正在做它的名字。使PByte变量,并做一个循环比较值和移动两个指针 - 你会*功能*等效的纯粹的pascal代码。 asm例程只针对速度进行了优化,但基本上可以通过简单的循环比较字节后的所有字节来实现它的等效。也许你可以从FPC获得现成的Pure Pascal实现,但它确实很简单。两个PByte指针和一个循环 - 就是这样。 –

+0

这里是你的功能等同物:http://pastebin.com/HTZDHHxx –

4

CompareMem的二进制表示只是进行逐字节比较字节。有些情况下,CompareMem未能通过值有效,平等的测试主要有两种方式:

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

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

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

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

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

相关问题