我在看 Delphi:Char和TCharArray数组“不兼容的类型” 并开始尝试。我发现的是相当有趣的。
procedure Clear(AArray: array of Integer);
var
I: Integer;
begin
for I := Low(AArray) to High(AArray) do
AArray[I] := 0;
end;
var
MyArray: array of Integer;
begin
Clear(MyArray);
end.
这个简单的小例子展示了如何使用Open Array参数将动态数组传递给过程。它完全按预期编译和运行。
procedure Clear(AArray: array of Char);
var
I: Integer;
begin
for I := Low(AArray) to High(AArray) do
AArray[I] := #0;
end;
var
MyArray: array of Char;
begin
Clear(MyArray);
end.
这里几乎是相同的代码唯一的区别是它使用的数组 Char
而不是 Integer
。它不编译。相反,编译器吐出:
E2010 Incompatible types: 'Array' and 'Dynamic array'
为什么会这样?
经过一段时间的搜索,我发现了 这个 QC报告。我正在运行Delphi 2009,它仍然在发生。
由于文档特别提到Char类型的开放数组参数与动态数组兼容,这应该是一个bug。从 '打开数组参数':
function Find(A: array of Char):
整数;
[...]
注意: [...]
上一个示例创建一个函数
它接受任何Char元素数组,
包括(但不限于)动态
阵列。 [...]
你可以使用这种数组,定义你自己的类型:
type
TCharDynArray = array of char;
procedure Clear(AArray: TCharDynArray);
var
I: Integer;
begin
for I := Low(AArray) to High(AArray) do
AArray[I] := #0;
end;
procedure test;
var
MyArray: TCharDynArray;
begin
Clear(MyArray);
end;
这段代码编译得很好。当然它没有做任何有用的事情(AArray参数没有设置为“var”,因此在为每个项目分配#0之前将它复制到堆栈上)。但至少,它编译。
在实践中,我发现更容易为动态数组定义或使用高级类型(如TIntegerDynArray),因为至少它允许您使用var将数组作为引用传递,因此避免在堆栈上进行复制,让你的代码更快。
关于到PChar的映射,通常用于所有动态数组:您可以将TIntegerDynArray映射到指针,然后将其用作PInteger或PIntegerArray:
procedure AddInteger(var Values: TIntegerDynArray; Value: integer);
var n: integer;
begin
n := Length(Values);
SetLength(Values,n+1);
Values[n] := Value;
end;
procedure Loop(V: PInteger);
begin
if V<>nil then
while V^<>0 do begin
write(V^,' ');
inc(V); // go to next integer in array
end;
end;
var IntArray: TIntegerDynArray;
begin
Loop(pointer(IntArray)); // will display nothing, since pointer(IntArray)=nil for IntArray=[]
AddInteger(IntArray,2);
AddInteger(IntArray,3);
AddInteger(IntArray,0);
Loop(pointer(IntArray)); // will display '2 3 '
end.
问题是“数组的char”代码与“整数数组”不一致当然是在编译器内在函数中,并且事实上PChar可以被类型转换为字符串。
我认为原因是 array of Char
兼容 PChar
,因为这段代码编译:
procedure Clear(AArray: array of Char);
var
I: Integer;
begin
for I := Low(AArray) to High(AArray) do
AArray[I] := #0;
end;
var
MyArray: array of Char;
P: PChar;
begin
Clear(P^);
end.
这可能是出于历史原因。
希望 巴里凯利 要么 丹尼索普 将启动并提供更多反馈。
--jeroen