11

我在看Delphi: array of Char and TCharArray "Incompatible Types"并开始试验。我的发现相当有趣。

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,它仍在发生。

4

3 回答 3

4

由于文档特别提到 Char 类型的开放数组参数与动态数组兼容,因此这应该是一个错误。从“开放数组参数”

function Find(A: array of Char): 整数;
[...]
注意: [...] 前面的示例创建了一个函数,该函数接受任何 Char 元素数组,包括(但不限于)动态数组。[...]

于 2010-09-24T01:10:56.343 回答
4

您可以使用这种数组,定义自己的类型:

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.

问题是与“整数数组”不一致的“字符数组”代码肯定是在编译器内在函数中,而且 PChar 可以类型转换为字符串这一事实。

于 2011-01-06T08:55:46.197 回答
2

我认为原因是与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.

这可能是出于历史原因。
希望Barry KellyDanny Thorpe能够参与进来并就此提供更多反馈。

——杰伦

于 2010-09-23T19:38:50.020 回答