当我尝试将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]
但是,在rutine的末尾,两个值arr[1]
和baaa
等于{{1}} 。我想这与类型转换有关。
任何人都可以看到有什么问题吗?
答案 0 :(得分:5)
您的代码存在两个问题:
您的循环超出了数组的上限。它需要使用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;
取决于RTL内存管理器在运行时如何管理compiler_temp
的内存,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;