3

当我尝试将字符串从Lines控件TMemo传递到PChar. 在例程结束时,数组中的最后一个字符串被复制。我能够在这个简单的代码中复制它:

procedure Test;
var
  i: smallint;
  arr: array of PAnsiChar;
  strarr: array[0..1] of string;
begin
  SetLength(arr, 2);
  strarr[0] := 'abbb';
  strarr[1] := 'baaa';

  for i := 0 to Length(strarr) do
    arr[i] := PAnsiChar(AnsiString(strarr[i]));
end;

但是,如果我逐步运行此过程,我可以看到arr[0] = 'abbb',在常规结束时,两个值arr[0]arr[1]等于baaa. 我想这与类型转换有关。

谁能看到有什么问题?

4

1 回答 1

5

您的代码有两个问题:

  1. 您的循环超出了数组的上限。它需要使用for i := 0 to Length(strarr)-1 doorfor i := 0 to High(strarr) do代替。

  2. 更重要的是,当您将 an 类型强制AnsiString转换为 a时,如果 a不为空PAnsiChar,它会返回一个指向AnsiString内部数据的指针。AnsiString您将 a 类型转换UnicodeString为 anAnsiString并获取指向它的指针,因此编译器必须为AnsiString数据使用编译器生成的局部变量。换句话说,您的代码实际上正在执行与以下相同的操作:

    procedure Test;
    var
      i: smallint;
      arr: array of PAnsiChar;
      strarr: array[0..1] of string;
      compiler_temp: AnsiString;
    begin
      SetLength(arr, 2);
      strarr[0] := 'abbb';
      strarr[1] := 'baaa';
      for i := 0 to Length(strarr) do
      begin
        compiler_temp := AnsiString(strarr[i]);
        arr[i] := PAnsiChar(compiler_temp);
      end;
    end;
    

根据compiler_tempRTL 内存管理器在运行时对内存的管理方式,在这种情况下,当然有可能arr[0]最终arr[1]指向同一个物理内存块。

如果你想要一个PAnsiChar值数组,那么你需要从一个Ansi数据数组开始,让它们指向:

procedure Test;
var
  i: Integer;
  arr: array of PAnsiChar;
  strarr: array[0..1] of AnsiString;
begin
  SetLength(arr, 2);
  strarr[0] := 'abbb';
  strarr[1] := 'baaa';
  for i := 0 to Length(strarr)-1 do
    arr[i] := PAnsiChar(strarr[i]);
end;
于 2013-02-10T05:31:04.763 回答