当我尝试将字符串从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
。我想这与类型转换有关。谁能看到什么地方不对?
最佳答案
您的代码有两个问题:
您的循环超出了数组的上限。它需要改用for i := 0 to Length(strarr)-1 do
或for i := 0 to High(strarr) do
。
更重要的是,当将AnsiString
强制类型转换为PAnsiChar
时,如果AnsiString
不为空,它将返回指向AnsiString
内部数据的指针。您正在将UnicodeString
类型转换为AnsiString
并抓住一个指针,所以编译器必须对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_temp
的内存在运行时由RTL内存管理器管理的方式,在这种情况下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;