6

以下代码在我的系统中按预期运行,但我不确定P变量在更改为新值后是否保证具有相同的值。MyArray[0]

procedure Test;
var
  MyArray: array of string;
  P : PChar;

begin
  SetLength(MyArray, 2);
  MyArray[0] := 'ABCD';
  MyArray[1] := '1234';

  // Is P guaranteed to have the same value all the time?
  P := PChar(MyArray[0]);

  MyArray[0] := MyArray[1];
  MyArray[1] := P;

  WriteLn(MyArray[0]);
  WriteLn(MyArray[1]);
end;
4

2 回答 2

13

您的代码在技术上无效。由于不应该依赖的实现细节,它只运行。

让我们看一下代码的相关部分:

P := PChar(MyArray[0]);
MyArray[0] := MyArray[1];
MyArray[1] := P;   

首先我们让 P 指向 MyArray[0] 的第一个字符。然后我们分配给 MyArray[0]。此时,没有理由让 P 指向的字符串缓冲区保持活动状态。没有字符串变量引用它。它的引用计数变为零,因此应该释放它。这使得 P 的后续使用无效。

在这种情况下,为什么你的代码会运行?因为您使用的字符串恰好是文字。因此它们以等于 -1 的引用计数存储并绕过字符串使用的正常堆分配例程。但是,如果您要使用不是文字的字符串值,那么我在上一段中描述的内容就会实现。而且我希望您的真实代码不使用文字。

所以你的实际问题有点没有实际意义。P 指针只指向一块内存。在您修改指针之前,它一直指向同一个内存块。如果您修改了内存块的内容,那么如果您取消引用它,P 将看到这些修改。它只是一个指针,就像任何其他指针一样。

您需要小心使用 PChar 变量。在您的使用中,它是指向编译器托管对象的非托管指针。这为错误提供了很大的空间,你已经掉进了陷阱。如果您想要一个字符串的副本,请将副本复制到另一个字符串变量中。

于 2012-12-29T08:09:52.657 回答
2

从字符串到 PChar 的类型转换似乎与获取其地址不同。请参见下面的代码,它将获取字符串的地址。

procedure Test;
var
  MyArray: array of string;
  P : ^String;

begin
  SetLength(MyArray, 2);
  MyArray[0] := 'ABCD';
  MyArray[1] := '1234';

  // take the pointer
  P := @MyArray[0];

  WriteLn(MyArray[0]);
  WriteLn(MyArray[1]);
  WriteLn(P^);

  // when content of array changes, P^ will change as well
  MyArray[0] := 'HELLO';
  WriteLn(P^);
end;
于 2012-12-29T08:34:38.627 回答