Delphi CompareMem和指针

nrj*_*one 3 delphi

我一直在使用DUnit作为TDD的驱动程序在Delphi 5中开发一些软件但我发现在使用CheckEqualsMem时它仍然失败,即使在调试器中我可以看到被比较的对象(在这种情况下是两个长字的数组)相同.

在内部,CheckEqualsMem使用CompareMem,发现这是返回false的内容.

深入研究我发现,如果我使用@或Addr调用CompareMem指向对象地址的指针,即使内存相同,CompareMem也会失败,但如果我使用PByte(来自windows)或PChar,它会正确地比较内存.

为什么?

这是一个例子

var
  s1  : String;
  s2  : String;
begin
  s1 := 'test';
  s2 := 'tesx';

  // This correctly compares the first byte and does not return false 
  // since both strings have in their first position
  if CompareMem(PByte(s1), PByte(s2), 1) = False then
    Assert(False, 'Memory not equal');

  // This however fails ?? What I think I am doing is passing a pointer
  // to the address of the memory where the variable is and telling CompareMem
  // to compare the first byte, but I must be misunderstanding something
  if CompareMem(@s1,@s2,1) = False then
    Assert(False,'Memory not equal');

  // Using this syntax correctly fails when the objects are different in memory
  // in this case the 4th byte is not equal between the strings and CompareMem
  // now correctly fails
  if CompareMem(PByte(s1),PByte(s2),4) = False then
     Assert(False, 'Memory not equal');
end;
Run Code Online (Sandbox Code Playgroud)

正如你在评论中看到的那样,我来自C背景,所以我认为@ s1是指向s1的第一个字节的指针而PByte(s1)应该是同一个东西,但它不是.

我在这里误解了什么?@/Addr和PByte有什么区别?

klu*_*udg 6

不同的是,@s1地址可变的s1而PBYTE(S1)是的可变的s1.

内部的字符串变量是指向字符串数据@s1的指针,因此是指向指针的指针.这条线

CompareMem(@s1,@s2,1);
Run Code Online (Sandbox Code Playgroud)

比较地址s1s2字符串的两个最低有效字节; 它没有任何意义,没有关系由引用的字符串数据Pointer(s1)Pointer(s2).